Beliebte Suchanfragen
//

Using the New Context API with Higher Order Components in React

10.6.2018 | 3 minutes of reading time

What is the new Context API and what problem does it solve?

React Context API is a feature used for sharing the global state and passing it all the way down through the components tree. This can be useful when we need to pass some props from the parent component A, down to the child component C which is a child of component B.

Let’s consider this hypothetical code example:

1class A extends React.Component {
2  state = {
3    value: 'Some value'
4  };
5 
6  render() {
7    return(
8      <B value={this.state.value} />
9    );
10  }
11}
12 
13const B = (props) => (
14  <C value={props.value} />
15);
16 
17const C = (props) => (
18  <div>{props.value}</div>
19);

In this example, we are sending value from the parent component A through its child component B, to be used only inside the child component C. Component B doesn’t care about the value prop, and it’s only passing down that prop to be used in component C.

This is something commonly known as Prop Drilling – passing props down from an upper level to a lower level in the components tree, while components in between don’t care about these props.

When to use Context?

As React’s official documentation suggests, you shouldn’t use Context just to avoid passing props a few levels down, but rather when you need to share the same data in many different components at multiple levels (e.g. theming, localization, authentication, etc.).

1// AuthUser.jsx
2import React, { Component } from 'react';
3import { authenticateUser } from './Auth';
4 
5// initialize Context with default value
6export const AuthCtx = React.createContext(null);
7 
8const AuthenticateUser = (ComposedComponent) => {
9  class Authenticate extends Component {
10    state = {
11      userAuth: null
12    };
13 
14    async componentDidMount() {
15      try {
16        // make API request to authenticate user on the backend
17        const { status, data } = await authenticateUser();
18        if (status === 200) {
19          this.setState({ userAuth: data });
20        }
21      } catch (err) {
22        // handle error
23      }
24    }
25 
26    render() {
27      const { userAuth } = this.state;
28      return(
29        <AuthCtx.Provider value={userAuth}>
30          <ComposedComponent />
31        </AuthCtx.Provider>
32      );
33    }
34  }
35  return Authenticate;
36};
37 
38export default AuthenticateUser;

We’ve first created Context using the createContext() method, which returns Provider and Consumer objects. We are passing userAuth to the Provider’s prop, value making it available to all of its children, so that AuthCtx’s Consumer instance below in the hierarchy tree can access (consume) it.

We’ve implemented AuthenticateUser reusable Higher Order Component to abstract business logic. This HOC returns ComposedComponent passed as an argument that we’ve just wrapped into Context’s Provider component.

Next, we are going to use this Higher Order Component to enhance and wrap our NavBar component:

1// NavBar.jsx
2import React from 'react';
3import { Link } from 'react-router-dom';
4import AuthenticateUser, { AuthCtx } from './AuthUser';
5 
6const NavBar = () => (
7  <div className="nav-bar">
8    <AuthCtx.Consumer>
9      {userAuth =>
10        !userAuth ? (
11          <Link to="/login">Login</Link>
12        ) : (
13          <Link to="/profile">Profile</Link>
14          <Link to="/logout">Logout</Link>
15          ...
16        )
17      }
18    </AuthCtx.Consumer>
19  </div>
20);
21 
22export default AuthenticateUser(NavBar);

Consumer subscribes to the context’s changes, and it uses the render props pattern to consume provided userAuth context.

Conclusion

Whenever we need to display some data only if a user is logged in, we can now simply wrap that component with the AuthenticateUser higher-order component to provide the context, and check if user is authenticated inside the component, just like we did for the NavBar.

share post

Likes

0

//

More articles in this subject area

Discover exciting further topics and let the codecentric world inspire you.

//

Gemeinsam bessere Projekte umsetzen.

Wir helfen deinem Unternehmen.

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.