ReactJS : context

16 Feb 2016

When my app grown to large app with lots of nested components, passing data from top to inner components via props have become really nasty. This felt like a code smell to me and it’s started really difficult to maintain as well. That’s when I found the React’s experimental feature called context.

Please not that this is a experimental feature and the api might change in future.

React’s context helps to pass the data to component tree without passing through each of the intermediate components. Even though this is against the philosophy of react ie., react always favor explicit data flow where as context make it implicit.

While using context we need to know three things, getChildContext, childContextTypes and contextTypes.

we need to specify getChildContext method in top component and return an object with data which we wish to pass via context.

const {PropTypes, Component} = React;
const {render} = ReactDOM;

class App extends Component {
  getChildContext() {
    return {items: ['A', 'B', 'C']};
  }
  render() {
    return (
      <List />
    );
  }
}

App.childContextTypes = {
  items: PropTypes.array
}

Also we need to specify the what all data we are passing through context need to be specified in childContextTypes of top component. If we miss specifying in childContextTypes the child won’t be able to receive those data.

Now in the child component where we need to receive data we need to specify all data need to receive in contextTypes. Once that this done, we can access data in child component using this.context.

In the above example you can see that I am missing the <List /> component (which we will fill in next example) and also you can see I am not passing any props to <List />.

// imports from above example

class List extends Component {
  render() {
    return (
      <ul>
        {
          this.context.items.map((item) => {
            return <li>{item}</li>;
          })
        }
      </ul>
    )
  }
}

List.contextTypes = {
  items: PropTypes.array
}

// app component from above example

Now the code snippet looks like

const {PropTypes, Component} = React;
const {render} = ReactDOM;

class List extends Component {
  render() {
    return (
      <ul>
        {
          this.context.items.map((item) => {
            return <li>{item}</li>;
          })
        }
      </ul>
    )
  }
}

List.contextTypes = {
  items: PropTypes.array
}

class App extends Component {
  getChildContext() {
    return {items: ['A', 'B', 'C']};
  }
  render() {
    return (
      <List />
    );
  }
}

App.childContextTypes = {
  items: PropTypes.array
}

render(<App />, document.getElementById('mount'));

You can find an working example in jsbin.

If you find my work helpful, You can buy me a coffee.