Technology Blog

Look deep into latest news and innovations happening in the Tech industry with our highly informational blog.

React Context API  –  A Replacement for Redux?

hkis

React Context API — What is it?

With React is urging us to migrate to the new Context API. Context provides a way to pass data through the component tree without having to pass props down manually at every level.

In React, data is often passed from a parent to its child component as a prop.

This method has worked well in the past, but is not suitable for every kind of data. It will make things difficult later when moving components around. props even get passed down to child components which aren’t using the data.

React_context_api

Is Context API a new thing?

The truth is that Context has been a part of React for a really long time.

Remember the <Provider> tag that we used earlier in the Redux app? It is actually a part of the older React Context API. React Context API is even used by libraries such as react-redux, MobX-react, react-router, and glamorous.

So why is React Context API making such a big noise now?

React used to discourage developers from directly using it in their apps and it was only included on an experimental basis. Now, with official support + the ability to render props, Context brings us a delightful new experience.

How to use this new version of Context?

The new context API consists of three main steps:

  • React.createContext is passed the initial value. It returns an object with a Provider and a Consumer.
  • The Provider component is used higher in the tree and accepts a prop called value. This value can be anything!
  • The Consumer component is used anywhere below the Provider in the tree and accepts a prop called children and must be a function that can accept a value and return a JSX.

Let’s take an in-detail look at how to use React Context API by migrating the earlier app from Redux to React Context API.

Converting the Redux App to React Context

First, let’s remove all traces of Redux from our code. Delete the Reducer.js and Actions.js from the src folder.

You can also remove the redux and react-redux dependencies. Simply run:

$ yarn remove redux react-redux

With that taken care of, let’s begin writing our app with React Context API.

To convert the previous app to Context API, I first need to create a context to store the data in. This context will replace the Redux Store.

I will also have to create a Context.Provider component, which will act just like a normal React component. This React component will have a state and props and a component lifecycle.

Create file named Provider.js in the src folder. Inside, store the default values in the state and pass them down in the render, through the value prop.

import React from 'react';
import Char from './hero';

const DEFAULT_STATE = {
  allChar: Char,
  searchTerm: '',
};

export const ThemeContext = React.createContext(DEFAULT_STATE);

export default class Provider extends React.Component {
  state = DEFAULT_STATE;

  searchTermChanged = searchTerm => {
    this.setState({searchTerm});
  };

  render() {
    return (
      <ThemeContext.Provider value={{ ...this.state, searchTermChanged: this.searchTermChanged, }} >
        {this.props.children}
      </ThemeContext.Provider>
    );
  }
}

Provider.js

Note: You can use the same hero.js file as the one you had used in the Redux version of the app. Use the same code snippet as the one I had showed above.

export default [
  {
    name: 'Amethyst',
    alter_ego: 'Amy Winston',
    first_appearance: 'LEGION OF SUPER-HEROES #298 (1983)',
  },
  {
    name: 'Aquaman',
    alter_ego: 'Arthur Curry',
    first_appearance: 'MORE FUN COMICS #73 (1941)',
  },
  {
    name: 'Arsenal',
    alter_ego: 'Roy Harper',
    first_appearance: 'ADVENTURE COMICS #250 (1958)',
  },
  {
    name: 'Atom',
    alter_ego: 'Ray Palmer',
    first_appearance: 'SHOWCASE #34 (1961)',
  },
  {
    name: 'Batgirl',
    alter_ego: 'Barbara Gordon',
    first_appearance: 'BATMAN #139 (1961)',
  },
  {
    name: 'Batman',
    alter_ego: 'Bruce Wayne',
    first_appearance: 'DETECTIVE COMICS #27',
  }
];

hero.js

In most cases, we’ll want to render {this.props.children}, as we’re likely to just render this component class high up in our component tree, above any place where we might want to consume it.

We want our action handlers to be able to modify our state, and propagate its value down. So we will create component methods that will call this.setState to trigger re-renders. Furthermore, if we want to make those action handlers available later down the tree, we will need to also make them accessible in the value prop.

To consume these values later in the component tree, we will need to create a ThemeContext.Consumer component. This component will need a render prop that will receive the above value prop as an argument.

Create another file called Consumer.js in the src folder and write the following code in it.

import React from 'react';
import {ThemeContext} from './Provider';

export default class Consumer extends React.Component {
  render() {
    const {children} = this.props;

    return (
      <ThemeContext.Consumer>
        {({allChar, searchTerm, searchTermChanged}) => {
          const char = searchTerm
            ? allChar.filter(
                char =>
                  char.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1
              )
            : allChar;

          return React.Children.map(children, child =>
            React.cloneElement(child, {
              char,
              searchTerm,
              searchTermChanged,
            })
          );
        }}
      </ThemeContext.Consumer>
    );
  }
}

Consumer.js

We will leave the App.js file as it is, except make sure to remove the import statement for react-redux and actions.js file. We only have one thing left to do. Open your index.js file and inside the render() function, wrap the App component inside <Consumer> component and wrap that inside the <Provider> component as shown here:

import React from 'react';
import ReactDOM from 'react-dom';
import Provider from './Provider';
import Consumer from './Consumer';
import App from './App';

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

index.js
And with that, we have a simple React App that uses React Context API to manage its state.

Redux or Context — When To Use What?

Each app is different, which also means that each app’s needs are different.

Some apps may work best with Redux, while others may work best with React Context API.Others might even need something like Mobx or Mobx-State-Tree, and some may not need anything to handle their state at all.

So, how do you decide?

The answer comes with experience. But I will try help you make your decision by explaining some of the best use cases for Redux and React Context API.

Redux

The point at which we want to start thinking about Redux is when our app’s state is global.

But you will probably have very less amount of state that will be global.Which brings us to an important take away:

Use both local and global state in your apps.

Managing everything in Redux is overkill. It may have negative performance implications and will increase the complexity of your app, making it hard to refactor, and likely reduce the reusability of many of your components.

But I am going off on a tangent here. Getting back to the topic, when do I use Redux?

Say you are building a food-ordering website. We have a checkout page that shows the food items a user has ordered with their respective prices and the total checkout price.

We manage all of this state with a local component state in the Checkout component. Then, we implement the NavBar component which shows the number of food items in the user’s cart and the total checkout price.

But we already have this data managed and rendered in the Checkout component. Also, you want both the Checkoutcomponent and NavBar component to stay in sync as the contents of the cart change. In other words, we have two disparate components that need to read and possibly update the same state.

So you need to pull the checkout cart state of our Checkout component up into Redux. Once this data is in Redux, the Checkout and NavBar components can individually connect to Redux with the state and dispatch functions they need.

React Context API

React Context API is used when all you want is a simple state management. It can also be used in apps where you want to pass some props deeply without the overkill that comes with Redux or MobX.

But the new Context API has its own limitations.

For example, it encourages the use of immutable or persistent data structures or strict comparison of context values which might prove difficult because many common data sources rely on mutation.

Another limitation is that the new Context API only allows for a Consumer to read values from a single Provider type, one consumer to one provider. Unlike the current API, which allows a Consumer to connect to multiple Providers.

For more Information and to build website using React.js, Hire React.js Developer from us as we give you high quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.

To develop custom web app using React.js, please visit our technology page.

Content Source:

  1. blog.bitsrc.io