freeCodeCamp/guide/english/react/context-api/index.md

3.9 KiB
Raw Blame History

title
Context API

Context API

The Context API has been implemented in the 16.3 version of React.

It existed before, but was in beta, and thus, unadvised to work with.

The goal of Context API is to allow developers to have an easy communication between components, without needing them to be closely related (Parent/Children components). This also reduce the need for prop drilling (passing down the props through several components), which allows for a cleaner code, easier to maintain and update.

This get to its full potential when we want to share data that will be accessed by multiple components.

This is based around two things : a Provider and a Consumer.

Provider

On a file created exclusively to provide data, TimeProvider.js, lets say we want to share some time between components.

// Import createContext
import React, { createContext, Component } from 'react';

// Initialize a context with a time value to it
export const TimeContext = createContext({
  time: '',
});

// Create the TimeProvider class to be used by index.js as a provider and initialize a default value
class TimeProvider extends Component {
  state = {
    time: '17:00',
  };

  // Passing the state that we just set as value to be used by our consumer and returning its children
  render() {
    return (
      <TimeContext.Provider value={this.state}>
        {this.props.children}
      </TimeContext.Provider>
    );
  }
}

export default TimeProvider;

We need to tweak a bit the component that will call the child which needs to consume our context ( in this case).

// index.js
import React from "react";
import ReactDOM from "react-dom";
import { ShowTime} from "./ShowTime";

// Importing our provider
import TimeProvider from "./utils/timeProvider";

// Calling our Hello component inside our provider
function App() {
  return (
      <TimeProvider>
        <ShowTime />
      </TimeProvider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Consumer

In the ShowTime.js file, let's call the time value using the consumer :

// on ShowTime.js
import React from react;

import { TimeContext } from ./utils/TimeProvider;

export default () => (
  <TimeContext.Consumer>
    {value => <p> Its {value.time} ! </p>}
  </TimeContext.Consumer>
);

This should show :

<p> Its 17:00 ! </p>

Modify the context dynamically

In order to change the time that well provide to the ShowTime component, we need to give our context a function, that can be used by the consumer to update a value.

Lets just add it to our Provider

// utils.TimeProvider.js
...
// This time we initialize a function to set the time
export const TimeContext = createContext({
  time: "",
  setTime: () => {}
});

// We define the setTime function to store the time well give it
class TimeProvider extends Component {
  state = {
    time : "17:00",
    setTime: time => this.setState({ time : time })
  };

  render() {
    return (
      <TimeContext.Provider value={this.state}>
        {this.props.children}
      </TimeContext.Provider>
    );
  }
}

export default TimeProvider;

And back on our Consumer :

// on ShowTime.js
import React from react;

import { TimeContext } from ./utils/TimeProvider;

export default () => (
  <TimeContext.Consumer>
    {value => <p> Its {value.time} ! </p>}
    <input type="text" value={time} onChange={e => setTime(e.target.value)} />
  </TimeContext.Consumer>
);

This will give us an input to modify the time thatll be displayed.

We need to remember using three things :

  • Create a Provider that will manage our data shared (also called a Store)
  • Create a Consumer that will communicate with the store
  • Surrounding our Consumer Component with the Provider created so it can use its data

More Information