DEV Community

Cover image for Seeing the light with React.Context - Multiple React.Context in a class component
Carsten Daurehøj
Carsten Daurehøj

Posted on

Seeing the light with React.Context - Multiple React.Context in a class component

A question I quickly had to ask ask my self was: "How do you have multiple contexts in a React class component?" - useContext to the rescue

I've been working as a software engineer for +10 years where I basically only have been doing CRUD. At the end of last year I got an offer to join a company that has a physical piece of hardware as their product, with a react native app as client for this hardware. It didn't take me long to decide. It's a great company, with a great vision and roadmap.

The codebase wasn't how I imagined. All components was class components, written in the "old" react way using class components with .bind(this). A global context that was one big mess. No TypeScript - or PropTypes for the components.

Step 1 - The cleanup

One of my first pull requests was adding typescript and a testing framework and started to refactor most of the presentation components into functional components. In that process I also added some tests.

Step 2 - Cleanup App.js

Step 2 was splitting the HUGE (~800 lines including the global AppContext) App.js into multiple components and separating the AppContext into a file by it self. After doing this the whole app started to perform much better. Step 2 was now done.

Step 3 - Cleaning up the AppContext

Code was already starting to look better. The app was performing better. The next step was a bit more cleanup in the AppContext. I wanted to extract some of the AppContext into separate contexts - I'd rater have less lines and many file than one very large file with many lines.

One question I quickly had to ask ask my self was: "How do you have multiple contexts in a React class component?". I've spend some time reading up on this and didn't like the approach that was mentioned in the react documentation - Consuming Multiple Contexts. I'm a lazy developer and it just seemed like too much work and hard to maintain.

I've been working with Redux before and thought that I could use the same approach as Redux. Use a Higher Order Component to inject the context into the props of the component.

Instead of making a new HOC for each context I wanted some generic that could be used for all my new contexts and all components.

Step 4 - The withContext HOC

So how should I go about creating this. I wanted to inject the values of the context into the component- that part was clear.

Let me present useContext

import React, { useContext, ComponentType, Context, Component } from 'react'

export const withContext = <Props extends Record<string, any>>(contextName: string, context: Context<any>, WrappedComponent: ComponentType<Props>) =>
  (p: Props) => {
    return (
      <WrappedComponent
        {...{
          [contextName]: useContext(context),
          ...p
        }}
      />
    )
  }
Enter fullscreen mode Exit fullscreen mode

Example

class MyClassComponent extends Component {
  render() {
    return (
      <Text>This is my class component</Text>
    )
  }
}

export default withContext(
    'connection',
    ConnectionContext,
    MyClassComponent
)
Enter fullscreen mode Exit fullscreen mode

This works very well and is very easy to implement.

  • The first parameter of the HOC is the prop name that the context should have.
  • The second parameter name is the actual context
  • The third parameter is the component that the context should be injected to.

Conclusion

Using withContext will allow me to grab this.props.connection.isOnline to check if the phone is connected to the internet or not. To inject multiple contexts into my component I can use something like compose to loop thru all withContext and apply them to all of my class components.

Top comments (0)