React Context API Seems to re-render every component

Spencer Bigum picture Spencer Bigum · Jul 8, 2018 · Viewed 7k times · Source

I'm trying to use the new Context API in my app and it looks like every time I update the context, it re-renders any component connected to it regardless. I have a sandbox demo setup to see code and working issue. When you type in the input - the buttons context is rendered and vice-versa. My original thinking was that if you type in the input, only the input context would be printed out.

DEMO

Is this how it works or am I missing something? Thanks, Spencer

Answer

pedrobern picture pedrobern · Apr 16, 2019

The way I avoid re-rendering with react context API:

First I write my component as pure functional component:

const MyComponent = React.memo(({
    somePropFromContext,
    otherPropFromContext, 
    someRegularPropNotFromContext  
}) => {
    ... // regular component logic
    return(
        ... // regular component return
    )
});

Then I write a function to select props from context:

function select(){
  const { someSelector, otherSelector } = useContext(MyContext);
  return {
    somePropFromContext: someSelector,
    otherPropFromContext: otherSelector,
  }
}

I have my connect HOC wrote:

function connect(WrappedComponent, select){
  return function(props){
    const selectors = select();
    return <WrappedComponent {...selectors} {...props}/>
  }
}

All together

import connect from 'path/to/connect'

const MyComponent ... //previous code

function select() ... //previous code

export default connect(MyComponent, select)

Usage

<MyComponent someRegularPropNotFromContext={something} />

Demo

Demo on codesandbox

Conclusion

MyComponent will re-render only if the specifics props from context updates with a new value, if the value is the same, it will not re-render. Also it avoid re-rendering on any other value from context that is not used inside MyComponent. The code inside select will execute every time the context updates, but as it does nothing, its ok, since no re-rendering of MyComponent is wasted.