Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does new React Context API trigger re-renders?

I have been trying to understand the new React Context API and was playing with it. I just wanted to check a simple case - what all re-renders when data to a Provider is updated.

Check this small example on Codesandbox

So, in my example, I have an App component - that has state something like this --

this.state = {   number - A random number   text - A static text }  

I create a new React Context from here containing number and text from state and pass the values to two Consumers Number and Text.

So my assumption is if the random number updates, it will change the context and both the components should trigger re-render.

But in reality, the value is updating but no rerender is happening.

So, my question -

  1. Are updated to the context not propagated via the ususal rerenders? As I cannot see my logs / color changes when context changes.

  2. Are all the consumers to that Provider updated or not?

like image 221
Sachin Avatar asked Jun 12 '18 12:06

Sachin


People also ask

Does context API trigger re-render?

The updates to context values doesn't trigger re-render for all the children of the provider, rather only components that are rendered from within the Consumer, so in your case although number component contains the Consumer, Number component isn't re-rendered, rather just the render function within the Consumer and ...

Does React re-render context change?

It is a common pattern to “lift the state” up the component tree to a “Least-Common Ancestor” React Component if a state is shared amongst multiple sibling Components. But, the child component that should not be functionally dependent upon the 'lifted' state will re-render when the state changes.

What triggers re-renders in React?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.


1 Answers

Are updated to the context not propagated via the ususal rerenders? As I cannot see my logs / color changes when context changes.

The updates to context values doesn't trigger re-render for all the children of the provider, rather only components that are rendered from within the Consumer, so in your case although number component contains the Consumer, Number component isn't re-rendered, rather just the render function within the Consumer and hence the value changes on context updates. This way it is quite a lot performant as it doesn't trigger re-renders for all of its children.

Are all the consumers to that Provider updated or not ?

All consumers to that Provider will go through an update cycle but whether or not they re-render is decided by the react virtual DOM comparison. A demo of this you can see in the console for this sandbox

EDIT

What you need to make sure is that the components are rendered as children of the ContextProvider component and you are passing handlers to it instead of rendering them inline and updating the state of ContextProvider because that will trigger a re-render of all components that are within the ContextProvider

Performant usage

App.js

  constructor() {     super();     this.state = {       number: Math.random() * 100,       text: "testing context api"       updateNumber: this.updateNumber,     };   }   render() {     return (       <AppContext.Provider         value={this.state}       >         {this.props.children}       </AppContext.Provider>     );   } 

index.js

class Data extends React.Component {   render() {     return (       <div>         <h1>Welcome to React</h1>         <Number />         <Text />         <TestComp />         <AppContext.Consumer>           {({ updateNumber }) => (             <button onClick={updateNumber}>Change Number </button>           )}         </AppContext.Consumer>       </div>     );   } }  const rootElement = document.getElementById("root"); ReactDOM.render(   <App>     <Data />   </App>,   rootElement ); 

Less Performant usage

App.js

class App extends Component {   constructor() {     super();     this.state = {       number: Math.random() * 100,       text: "testing context api"     };   }    updateNumber = () => {     const randomNumber = Math.random() * 100;     this.setState({ number: randomNumber });   };    render() {     return (       <AppContext.Provider value={this.state}>         <div>           <h1>Welcome to React</h1>           <Number />           <Text />           <TestComp />           <button onClick={this.updateNumber}>Change Number </button>         </div>       </AppContext.Provider>     );   } } 
like image 80
Shubham Khatri Avatar answered Sep 23 '22 20:09

Shubham Khatri