Does new React Context API trigger re-renders?












6















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 a a 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 are updating but no rerender is happening.



So, my question -




  1. Does updates to context are 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 ?











share|improve this question





























    6















    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 a a 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 are updating but no rerender is happening.



    So, my question -




    1. Does updates to context are 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 ?











    share|improve this question



























      6












      6








      6








      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 a a 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 are updating but no rerender is happening.



      So, my question -




      1. Does updates to context are 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 ?











      share|improve this question
















      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 a a 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 are updating but no rerender is happening.



      So, my question -




      1. Does updates to context are 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 ?








      javascript reactjs react-context






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jul 25 '18 at 5:16









      Shubham Khatri

      80.2k1497135




      80.2k1497135










      asked Jun 12 '18 at 12:49









      SachinSachin

      1,049521




      1,049521
























          1 Answer
          1






          active

          oldest

          votes


















          7















          Does updates to context are 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



            render() {
          return (
          <AppContext.Provider
          value={{ ...this.state, updateNumber: this.updateNumber }}
          >
          {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>
          );
          }
          }





          share|improve this answer


























          • I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

            – Spencer Bigum
            Jul 8 '18 at 14:51













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50817672%2fdoes-new-react-context-api-trigger-re-renders%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          7















          Does updates to context are 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



            render() {
          return (
          <AppContext.Provider
          value={{ ...this.state, updateNumber: this.updateNumber }}
          >
          {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>
          );
          }
          }





          share|improve this answer


























          • I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

            – Spencer Bigum
            Jul 8 '18 at 14:51


















          7















          Does updates to context are 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



            render() {
          return (
          <AppContext.Provider
          value={{ ...this.state, updateNumber: this.updateNumber }}
          >
          {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>
          );
          }
          }





          share|improve this answer


























          • I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

            – Spencer Bigum
            Jul 8 '18 at 14:51
















          7












          7








          7








          Does updates to context are 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



            render() {
          return (
          <AppContext.Provider
          value={{ ...this.state, updateNumber: this.updateNumber }}
          >
          {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>
          );
          }
          }





          share|improve this answer
















          Does updates to context are 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



            render() {
          return (
          <AppContext.Provider
          value={{ ...this.state, updateNumber: this.updateNumber }}
          >
          {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>
          );
          }
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 19 '18 at 12:35

























          answered Jun 12 '18 at 12:56









          Shubham KhatriShubham Khatri

          80.2k1497135




          80.2k1497135













          • I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

            – Spencer Bigum
            Jul 8 '18 at 14:51





















          • I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

            – Spencer Bigum
            Jul 8 '18 at 14:51



















          I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

          – Spencer Bigum
          Jul 8 '18 at 14:51







          I'm interested in this as I have a similar issue. To me because there are 2 console.logs and only one item changing - I think there are still 2 renders going on and I would think one of them is unnecessary. My thinking was that only one Item should update and thus one console.log - why isnt that the case here? And how would you achieve that outcome?

          – Spencer Bigum
          Jul 8 '18 at 14:51




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50817672%2fdoes-new-react-context-api-trigger-re-renders%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to change which sound is reproduced for terminal bell?

          Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

          Can I use Tabulator js library in my java Spring + Thymeleaf project?