How To Use React Context With Example

tags = [ JavaScript , React , ]

React 16.3 introduced a new way of handling the context API, a built-in state management tool which provides a native way to pass or store data in the component tree.

Context provides a way to pass data through the component tree without having to pass props down manually at every level. React docs

The steps for creating a context is as simple as:

  • Create a contextcreateContext().
  • Create a provider Provider.
  • Consume the provider Consumer.

Now let's create a message context using React.creaetContext, the message context will have a String message and a funciton setMesasge that returns a String.

Creating a context is like a way of declaring an object which will be later on consumed.

message-context.js

// Creating a context.
import React from "react";

const MessageContext = React.createContext({
  Message: "",
  setMessage: () => {}
});

export default MessageContext;

Every Context has two major properties Provider and Consumer.

The provider will be represented as MessageContext.Provider with an attribute called value, the value attribute is the context object.

The consumer will be represented as MessageContext.Consumer, The rule for consuming the context is that the consumer must be a child of the Provider.

The consumer context changes according to the nearest Provider above in the tree.

Message.js

import React from "react";
import MessageContext from "../contexts/message-context";
import MessageHandler from "./MessageHandler";

class Message extends React.Component {
  constructor(props) {
    super(props);
    // setMessage initialization
    this.setMessage = msg => {
      this.setState(state => {
        return {
          message: msg
        };
      });
    };

    this.state = {
      message: "mmm...",
      setMessage: this.setMessage
    };
  }
  render() {
    return (
      <React.Fragment>
        <MessageContext.Provider value={this.state}>
          <MessageContext.Consumer>
            {({ message, setMessage }) => (
              <div>
                <p>message: {message}</p>
                <MessageHandler handler={setMessage} />
              </div>
            )}
          </MessageContext.Consumer>
        </MessageContext.Provider>
      </React.Fragment>
    );
  }
}

export default Message;

We defined the Message Component with a state of message and setMessage, The setMessagefunction will change the component state once it's called with a msg parameter.

MessageHandler.js

import React from "react";
import PropTypes from "prop-types";
import Message from "./Message";
import MessageContext from "../contexts/message-context";

/**
 * MessageHandler
 * Handle MessageContext messages.
 */
class MessageHandler extends React.Component {
  static propTypes = {
    handler: PropTypes.func.isRequired
  };

  /**
   * Random message changer.
   */
  messageHandler = () => {
    let { handler } = this.props;
    if (!handler) {
      return;
    }
    let messages = ["Hello", "Hola", "مرحبا"];
    let randomIndex = Math.floor(Math.random() * messages.length);
    handler(messages[randomIndex]);
  };
  render() {
    return <button onClick={this.messageHandler}>Change message</button>;
  }
}

export default MessageHandler;

MessageHandler will handle changing the messages, On each click of the button it will randomize a message to be set in the Message state which will be directly connected to the MessageContext.