React Context API

The context API will finally become a first class citizen with the release of React 16.3.

What’s React Context API?

In some cases, you want to pass data through the component tree without having to pass the props down manually at every level. You can do this directly in React with the powerful context API.

But Facebook warns us not use the Context API!

The React documentation used to warn us not to use the context API given it was unstable, and now this not the case anymore. The Context API has a new make over now and it is not an experimental framwework anymore.

Before diving deep into nitty griity of this new reformed API, let’s find out why we need the Context API.

Why use context?

You may have experienced having to pass down props from parent components to the child components even though they are not useful for the parent. This is called prop drilling and it can get super annoying. Also if you had to move around your components, this can get even more troublesome.

What if there’s a way of accessing your data without having to pass it down as props? Well if you are using Redux, you are implicitly using context. Because the <Provider> component is actually using context itself to put the data into the context and the connect component pulls the data oput of the context.

Born again Context

Facebook has announced that they are going to release a stable yet rewamped version of the context API.

Let’s look at how we can use this shiny new API in code.

Create a file called PostContext.js. With the createContext from React package, create a context variable as below:

import { createContext } from 'react';

const PostContext = createContext([
  {
    title: 'Title',
    content: 'Content',
    author: 'Author'
  }
]);

export const PostProvider = PostContext.Provider;

export const PostConsumer = PostContext.Consumer;

Here we are exporting both the provider and the consumer, that gets created. The constructor of createContext is taking an object for the purpose of the initialisation.

Bootstrap records

We need to create a bootstrapper for our posts and a function that loads those posts. So let’s create that file next.

const posts = [
  {
    id: '0001',
    title: 'React Context API',
    content: 'New React API Context is finally ready',
    author: 'Sean Amarasinghe'
  },
  {
    id: '0002',
    title: 'Redux Sagas',
    content: 'How to implement Redux sagas',
    author: 'Harold Chang'
  },
  {
    id: '0003',
    title: 'Webpack 4',
    content: 'Changes in Webpack 4',
    author: 'John McMillan'
  }
];

export const loadPosts = () => Promise.resolve(posts);

Now we have the data we need to render, let’s look at how we can create the components we need to display the posts.

Components

Let’s start by creating a component for displaying posts.

import React from 'react';
import { PostConsumer } from './PostContext';

const Content = () => (
  <div className="main">
    <PostConsumer>
      {context =>
        context.map(({ id, title, content, author }) => (
          <div key={id}>
            <h1>{title}</h1>
            <p>{content}</p>
            <p>{author}</p>
            <hr />
          </div>
        ))
      }
    </PostConsumer>
  </div>
);

export default Content;

Now we have the posts, let’s create a container for this component

import React from 'react';
import Content from './Content';

const Page = () => (
  <div className="container">
    <Content />
  </div>
);

export default Page;

Now we have the container, we can easily render in our app.

import React from 'react';
import ReactDOM from 'react-dom';
import Page from './Page';
import { loadPosts } from './bootstrapper';
import { PostProvider } from './PostContext';

const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center'
};

class App extends React.Component {
  state = { posts: [] };

  componentDidMount() {
    loadPosts().then(posts => this.setState({ posts }));
  }

  render() {
    return (
      <div style={styles}>
        <PostProvider value={this.state.posts}>
          <Page />
        </PostProvider>
      </div>
    );
  }
}

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

We are passing in the data we need to the PostProvider component. This data will be again retrieved by the PostConsumer component inside the Content.js component.

Conclusion

React will soon remove the warnings for using context API and this is great news for refactoring existing components to use the Context API instead of props drilling.

Be first to comment

Leave a Reply