Posted

2 minutes read

React Context was introduced in React v0.16.3 and its main functionality is to pass data to child components without having to pass props at every level.

  • Let’s have a look at a simple example of a page that uses 3 components and understand how we used to pass the data in the component tree before React Context.

import React, {Component} from 'react';

class Parent extends Component {
    state = {
        age: 101
    }

    render () {
        return (
            <div>
                <h1>Father</h1>
                <Child age={this.state.age}/>
            </div>
        )
    }
}

class Child extends Component {
    render () {
        return (
            <div>
                <h1>Child</h1>
                <Grandchild age={this.props.age}/>
            </div>
        )
    }
}

class Grandchild extends Component {
    render () {
        return (
            <div>
                <h1>Grandchild age {this.props.age}</h1>
            </div>
        )
    }
}

export default Parent;

In the example above, we have 3 components, and all we want to do is from the Parent component, we want to send the age to the Grandchild component.

In order to achieve that we need to pass the props through the Child component (or any other intermediary component), until we can use the data in the desired component.

This causes a lot of boilerplate code to be generate, that can get pretty heavy if you have lots of data to be sent and a huge hierarchy.

React Context will make it much easier and simpler to be able to re-use same data in multiple components without having to pass each prop down the component tree.

  • Let’s check how we can re-write the above example with the help of React Context and it’s predefined API methods.
    • React.createContext
    • Context.Provider
    • Class.contextType
    • Context.Consumer

import React, {Component} from 'react';

const MyContext = React.createContext();

class MyProvider extends Component {
    state = {
        age: 101
    }

    render() {
        return (
            <MyContext.Provider value={{
                state: this.state,
                increaseAge: () => this.setState({
                    age: this.state.age + 1
                })
            }}>
                {this.props.children}
            </MyContext.Provider>

        )
    }
}

class MyComponentWithContext extends Component {
    render () {
        return (
            <MyProvider>
                <div>
                    <h1>Father</h1>
                    <Child />
                </div>
            </MyProvider>
        )
    }
}

class Child extends Component {
    render () {
        return (
            <div>
                <h1>Child</h1>
                <Grandchild />
            </div>
        )
    }
}

class Grandchild extends Component {
    render () {
        return (
            <div>
                <MyContext.Consumer>
                    {(context) => (
                        <div>
                            <h1>Grandchild age {context.state.age}</h1>
                            <button onClick={context.increaseAge}>Increase age</button>
                        </div>
                    )}
                </MyContext.Consumer>
            </div>
        )
    }
}

export default MyComponentWithContext;

Basically, we have created a new object called MyContext, which holds the data (state) and callback methods to update our state, and we wrap our whole application with this the MyContext.Provider.


class MyProvider extends Component {
    state = {
        age: 101
    }

    render() {
        return (
            <MyContext.Provider value={{
                state: this.state,
                increaseAge: () => this.setState({
                    age: this.state.age + 1
                })
            }}>
                {this.props.children}
            </MyContext.Provider>

        )
    }
}

In order get access to the data, we can get hold of it with MyContext.Consumer,


<MyContext.Consumer>
    {(context) => (
        <div>
            <h1>Grandchild age {context.state.age}</h1>
            <button onClick={context.increaseAge}>Increase age</button>
        </div>
    )}
</MyContext.Consumer>

Thanks for reading. I hope you learned something interesting about React!
If you found this article useful, please share it with others. Don’t forget to subscribe to get notified for the upcoming articles.