Introduction:

This article explains about Context API in React.

What?

The definition for the Context API according to the documentation is “Context provides a way to pass data through the component tree without having to pass props down manually at every level”.

In simple words, the Context is the universal data for your application. The Context API provides the solution for sharing the state between components in the component tree. Instead of passing properties through intermediary components that do not necessarily use the props (known as the "prop drilling"), you can wrap your components in a Context.

Why?

Let us take a step back and understand the scenarios/problems we end up with if we didn’t have the concept Context(Before Version 16.3).

In the following example, we have a Parent component and 2 levels of child components.

Component hierarchy

In a traditional way, if you want to use the Parent state in the GrandChild1 then you should pass the state to its child component as props. Let's take a look at the code below.

Code Sample without Context:

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      grandChild1Age: 10,
      grandChild2Age: 8
    };
  }
  render() {
    return (
      <div>
        <Child1
          rootName={this.props.name}
          grandChild1Age={this.state.grandChild1Age}
          grandChild2Age={this.state.grandChild2Age}
        />
        <Child2 />
      </div>
    );
  }
}

class Child1 extends React.component {
  render() {
    return (
      <div>
        <GrandChild1 age={props.grandChild1Age} rootName={props.rootName} />
        <GrandChild2 age={props.grandChild2Age} />
      </div>
    );
  }
}

class GrandChild1 extends React.Component {
  render() {
    return (
      <div>
        I am GrandChild1 and {props.age} old. My root name is {props.rootName}
      </div>
    );
  }
}

class GrandChild2 extends React.Component {
  render() {
    return (
      <div>
        I am GrandChild2 and {props.age} old. My root name is {props.rootName}
      </div>
    );
  }
}

Problems with the above Code:

Code Sample with Context:

const contextDemo = React.createContext();

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      grandChild1Age: 10,
      grandChild2Age: 8,
      rootName: props.name
    };
  }

  render() {
    return (
      <div>
        <contextDemo.Provider value={this.state}>
          <Child1 />
        </contextDemo.Provider>
      </div>
    );
  }
}

class Child1 extends React.Component {
  render() {
    return (
      <div>
        <GrandChild1 />
        <GrandChild2 />
      </div>
    );
  }
}

class GrandChild1 extends React.Component {
  render() {
    return (
      <contextDemo.Consumer>
        {context => (
          <div>
            I am GrandChild1 and {context.grandChild1Age} old. My root name is{" "}
            {context.rootName}
          </div>
        )}
      </contextDemo.Consumer>
    );
  }
}

class GrandChild2 extends React.Component {
  render() {
    return (
      <contextDemo.Consumer>
        {context => (
          <div>
            I am GrandChild and {context.grandChild2Age} old. My root name is{" "}
            {context.rootName}
          </div>
        )}
      </contextDemo.Consumer>
    );
  }
}

ReactDOM.render(<Parent name="AK" />, document.getElementById("root"));

Demystifying the above code snippet:

When to use Context API: