React compresses rendering, causing not updating components even if componentDidUpdate called












0















The React parent component rendering process automatically compresses rendering of child components. It can be a performance boost for most of application, but situation like this can be a serious problem.



I have 2 components :




  1. File list sidebar component

  2. Text editor component (I'm using Slate for now)


Two component is child component of Home component.



When user clicks the sidebar item, it should :




  1. Highlight the selected item

  2. Set a new editor state by reading the text file


Second step can be a bottleneck. The problem here is, that the React stupidly compresses the seperated two operations altogether.
This causes the user can't see item highlight right after click! User Must wait for reading the file, and set a new editor state, and then, finally, item can get highlighted.



This delay, is causing badly at user experience. Did you ever used a text editor that reacts your click about ~500ms after? The program looks "slower".



componentDidUpdate(prevProps) {
console.log('componentDidUpdate!');
const { currentDir, actions, currentFile } = this.props;
if (prevProps.currentDir !== currentDir) {
updatedFileList(currentDir);
} else if (prevProps.currentFile !== currentFile) {
updateEditorContent(currentFile);
}
}


This is the componentDidUpdate. This updates editor state.



redux-logger.js:1  action SELECT_FILE_LIST_ITEM @ 21:29:18.332
21:29:18.338 redux-logger.js:1 action UPDATE_CURRENT_FILE @ 21:29:18.338
21:29:18.347 Home.js:287 render!!
21:29:18.356 Home.js:44 componentDidUpdate!
21:29:18.366 redux-logger.js:1 action UPDATE_EDITOR_CONTENT @ 21:29:18.357
21:29:18.373 Home.js:287 render!!
21:29:18.678 Home.js:44 componentDidUpdate!


The log says it componentDidUpdated at 21:29:18.356, but actual HTML DOM is not updated yet. It acutally updates DOM after 21:29:18.678 Home.js:44 componentDidUpdate!.'



How to seperate two componentDidUpdates, to update DOM seperately?










share|improve this question





























    0















    The React parent component rendering process automatically compresses rendering of child components. It can be a performance boost for most of application, but situation like this can be a serious problem.



    I have 2 components :




    1. File list sidebar component

    2. Text editor component (I'm using Slate for now)


    Two component is child component of Home component.



    When user clicks the sidebar item, it should :




    1. Highlight the selected item

    2. Set a new editor state by reading the text file


    Second step can be a bottleneck. The problem here is, that the React stupidly compresses the seperated two operations altogether.
    This causes the user can't see item highlight right after click! User Must wait for reading the file, and set a new editor state, and then, finally, item can get highlighted.



    This delay, is causing badly at user experience. Did you ever used a text editor that reacts your click about ~500ms after? The program looks "slower".



    componentDidUpdate(prevProps) {
    console.log('componentDidUpdate!');
    const { currentDir, actions, currentFile } = this.props;
    if (prevProps.currentDir !== currentDir) {
    updatedFileList(currentDir);
    } else if (prevProps.currentFile !== currentFile) {
    updateEditorContent(currentFile);
    }
    }


    This is the componentDidUpdate. This updates editor state.



    redux-logger.js:1  action SELECT_FILE_LIST_ITEM @ 21:29:18.332
    21:29:18.338 redux-logger.js:1 action UPDATE_CURRENT_FILE @ 21:29:18.338
    21:29:18.347 Home.js:287 render!!
    21:29:18.356 Home.js:44 componentDidUpdate!
    21:29:18.366 redux-logger.js:1 action UPDATE_EDITOR_CONTENT @ 21:29:18.357
    21:29:18.373 Home.js:287 render!!
    21:29:18.678 Home.js:44 componentDidUpdate!


    The log says it componentDidUpdated at 21:29:18.356, but actual HTML DOM is not updated yet. It acutally updates DOM after 21:29:18.678 Home.js:44 componentDidUpdate!.'



    How to seperate two componentDidUpdates, to update DOM seperately?










    share|improve this question



























      0












      0








      0


      0






      The React parent component rendering process automatically compresses rendering of child components. It can be a performance boost for most of application, but situation like this can be a serious problem.



      I have 2 components :




      1. File list sidebar component

      2. Text editor component (I'm using Slate for now)


      Two component is child component of Home component.



      When user clicks the sidebar item, it should :




      1. Highlight the selected item

      2. Set a new editor state by reading the text file


      Second step can be a bottleneck. The problem here is, that the React stupidly compresses the seperated two operations altogether.
      This causes the user can't see item highlight right after click! User Must wait for reading the file, and set a new editor state, and then, finally, item can get highlighted.



      This delay, is causing badly at user experience. Did you ever used a text editor that reacts your click about ~500ms after? The program looks "slower".



      componentDidUpdate(prevProps) {
      console.log('componentDidUpdate!');
      const { currentDir, actions, currentFile } = this.props;
      if (prevProps.currentDir !== currentDir) {
      updatedFileList(currentDir);
      } else if (prevProps.currentFile !== currentFile) {
      updateEditorContent(currentFile);
      }
      }


      This is the componentDidUpdate. This updates editor state.



      redux-logger.js:1  action SELECT_FILE_LIST_ITEM @ 21:29:18.332
      21:29:18.338 redux-logger.js:1 action UPDATE_CURRENT_FILE @ 21:29:18.338
      21:29:18.347 Home.js:287 render!!
      21:29:18.356 Home.js:44 componentDidUpdate!
      21:29:18.366 redux-logger.js:1 action UPDATE_EDITOR_CONTENT @ 21:29:18.357
      21:29:18.373 Home.js:287 render!!
      21:29:18.678 Home.js:44 componentDidUpdate!


      The log says it componentDidUpdated at 21:29:18.356, but actual HTML DOM is not updated yet. It acutally updates DOM after 21:29:18.678 Home.js:44 componentDidUpdate!.'



      How to seperate two componentDidUpdates, to update DOM seperately?










      share|improve this question
















      The React parent component rendering process automatically compresses rendering of child components. It can be a performance boost for most of application, but situation like this can be a serious problem.



      I have 2 components :




      1. File list sidebar component

      2. Text editor component (I'm using Slate for now)


      Two component is child component of Home component.



      When user clicks the sidebar item, it should :




      1. Highlight the selected item

      2. Set a new editor state by reading the text file


      Second step can be a bottleneck. The problem here is, that the React stupidly compresses the seperated two operations altogether.
      This causes the user can't see item highlight right after click! User Must wait for reading the file, and set a new editor state, and then, finally, item can get highlighted.



      This delay, is causing badly at user experience. Did you ever used a text editor that reacts your click about ~500ms after? The program looks "slower".



      componentDidUpdate(prevProps) {
      console.log('componentDidUpdate!');
      const { currentDir, actions, currentFile } = this.props;
      if (prevProps.currentDir !== currentDir) {
      updatedFileList(currentDir);
      } else if (prevProps.currentFile !== currentFile) {
      updateEditorContent(currentFile);
      }
      }


      This is the componentDidUpdate. This updates editor state.



      redux-logger.js:1  action SELECT_FILE_LIST_ITEM @ 21:29:18.332
      21:29:18.338 redux-logger.js:1 action UPDATE_CURRENT_FILE @ 21:29:18.338
      21:29:18.347 Home.js:287 render!!
      21:29:18.356 Home.js:44 componentDidUpdate!
      21:29:18.366 redux-logger.js:1 action UPDATE_EDITOR_CONTENT @ 21:29:18.357
      21:29:18.373 Home.js:287 render!!
      21:29:18.678 Home.js:44 componentDidUpdate!


      The log says it componentDidUpdated at 21:29:18.356, but actual HTML DOM is not updated yet. It acutally updates DOM after 21:29:18.678 Home.js:44 componentDidUpdate!.'



      How to seperate two componentDidUpdates, to update DOM seperately?







      javascript reactjs redux react-redux






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 1 at 12:47







      Hoseong Son

















      asked Jan 1 at 12:28









      Hoseong SonHoseong Son

      67111




      67111
























          1 Answer
          1






          active

          oldest

          votes


















          0














          I think you should be able to solve this by triggering the second update asynchronously:



          componentDidUpdate(prevProps) {
          console.log('componentDidUpdate!');
          const { currentDir, actions, currentFile } = this.props;
          if (prevProps.currentDir !== currentDir) {
          updatedFileList(currentDir);
          } else if (prevProps.currentFile !== currentFile) {
          setTimeout(()=>{updateEditorContent(currentFile);}, 0);
          }
          }


          I didn't actually try this out, so I apologize if there are any syntax issues.



          In general, what React is doing is desirable -- not wasting time updating the DOM two times when one state update immediately triggers another state update. This avoids DOM flicker when both updates are quick.



          React is able to do this because it splits its work into two phases




          • a rendering/reconciliation phase in which React figures out what should be changed with the next update to the DOM

          • a commit phase where those updates are actually applied to the DOM


          When the rendering triggers another rendering, React will hold off on the commit phase and batch up the DOM updates for one commit. The setTimeout above will cause that state update to wait until after the commit phase for the first update.



          I think future React features around asynchronous mode will provide nicer ways of dealing with this kind of scenario where one update is high priority and the other is lower priority.






          share|improve this answer


























          • You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

            – Hoseong Son
            Jan 1 at 12:59








          • 1





            I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

            – Ryan Cogswell
            Jan 1 at 13:12











          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%2f53995431%2freact-compresses-rendering-causing-not-updating-components-even-if-componentdid%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









          0














          I think you should be able to solve this by triggering the second update asynchronously:



          componentDidUpdate(prevProps) {
          console.log('componentDidUpdate!');
          const { currentDir, actions, currentFile } = this.props;
          if (prevProps.currentDir !== currentDir) {
          updatedFileList(currentDir);
          } else if (prevProps.currentFile !== currentFile) {
          setTimeout(()=>{updateEditorContent(currentFile);}, 0);
          }
          }


          I didn't actually try this out, so I apologize if there are any syntax issues.



          In general, what React is doing is desirable -- not wasting time updating the DOM two times when one state update immediately triggers another state update. This avoids DOM flicker when both updates are quick.



          React is able to do this because it splits its work into two phases




          • a rendering/reconciliation phase in which React figures out what should be changed with the next update to the DOM

          • a commit phase where those updates are actually applied to the DOM


          When the rendering triggers another rendering, React will hold off on the commit phase and batch up the DOM updates for one commit. The setTimeout above will cause that state update to wait until after the commit phase for the first update.



          I think future React features around asynchronous mode will provide nicer ways of dealing with this kind of scenario where one update is high priority and the other is lower priority.






          share|improve this answer


























          • You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

            – Hoseong Son
            Jan 1 at 12:59








          • 1





            I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

            – Ryan Cogswell
            Jan 1 at 13:12
















          0














          I think you should be able to solve this by triggering the second update asynchronously:



          componentDidUpdate(prevProps) {
          console.log('componentDidUpdate!');
          const { currentDir, actions, currentFile } = this.props;
          if (prevProps.currentDir !== currentDir) {
          updatedFileList(currentDir);
          } else if (prevProps.currentFile !== currentFile) {
          setTimeout(()=>{updateEditorContent(currentFile);}, 0);
          }
          }


          I didn't actually try this out, so I apologize if there are any syntax issues.



          In general, what React is doing is desirable -- not wasting time updating the DOM two times when one state update immediately triggers another state update. This avoids DOM flicker when both updates are quick.



          React is able to do this because it splits its work into two phases




          • a rendering/reconciliation phase in which React figures out what should be changed with the next update to the DOM

          • a commit phase where those updates are actually applied to the DOM


          When the rendering triggers another rendering, React will hold off on the commit phase and batch up the DOM updates for one commit. The setTimeout above will cause that state update to wait until after the commit phase for the first update.



          I think future React features around asynchronous mode will provide nicer ways of dealing with this kind of scenario where one update is high priority and the other is lower priority.






          share|improve this answer


























          • You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

            – Hoseong Son
            Jan 1 at 12:59








          • 1





            I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

            – Ryan Cogswell
            Jan 1 at 13:12














          0












          0








          0







          I think you should be able to solve this by triggering the second update asynchronously:



          componentDidUpdate(prevProps) {
          console.log('componentDidUpdate!');
          const { currentDir, actions, currentFile } = this.props;
          if (prevProps.currentDir !== currentDir) {
          updatedFileList(currentDir);
          } else if (prevProps.currentFile !== currentFile) {
          setTimeout(()=>{updateEditorContent(currentFile);}, 0);
          }
          }


          I didn't actually try this out, so I apologize if there are any syntax issues.



          In general, what React is doing is desirable -- not wasting time updating the DOM two times when one state update immediately triggers another state update. This avoids DOM flicker when both updates are quick.



          React is able to do this because it splits its work into two phases




          • a rendering/reconciliation phase in which React figures out what should be changed with the next update to the DOM

          • a commit phase where those updates are actually applied to the DOM


          When the rendering triggers another rendering, React will hold off on the commit phase and batch up the DOM updates for one commit. The setTimeout above will cause that state update to wait until after the commit phase for the first update.



          I think future React features around asynchronous mode will provide nicer ways of dealing with this kind of scenario where one update is high priority and the other is lower priority.






          share|improve this answer















          I think you should be able to solve this by triggering the second update asynchronously:



          componentDidUpdate(prevProps) {
          console.log('componentDidUpdate!');
          const { currentDir, actions, currentFile } = this.props;
          if (prevProps.currentDir !== currentDir) {
          updatedFileList(currentDir);
          } else if (prevProps.currentFile !== currentFile) {
          setTimeout(()=>{updateEditorContent(currentFile);}, 0);
          }
          }


          I didn't actually try this out, so I apologize if there are any syntax issues.



          In general, what React is doing is desirable -- not wasting time updating the DOM two times when one state update immediately triggers another state update. This avoids DOM flicker when both updates are quick.



          React is able to do this because it splits its work into two phases




          • a rendering/reconciliation phase in which React figures out what should be changed with the next update to the DOM

          • a commit phase where those updates are actually applied to the DOM


          When the rendering triggers another rendering, React will hold off on the commit phase and batch up the DOM updates for one commit. The setTimeout above will cause that state update to wait until after the commit phase for the first update.



          I think future React features around asynchronous mode will provide nicer ways of dealing with this kind of scenario where one update is high priority and the other is lower priority.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 1 at 13:11

























          answered Jan 1 at 12:50









          Ryan CogswellRyan Cogswell

          5,066524




          5,066524













          • You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

            – Hoseong Son
            Jan 1 at 12:59








          • 1





            I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

            – Ryan Cogswell
            Jan 1 at 13:12



















          • You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

            – Hoseong Son
            Jan 1 at 12:59








          • 1





            I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

            – Ryan Cogswell
            Jan 1 at 13:12

















          You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

          – Hoseong Son
          Jan 1 at 12:59







          You're right. That solves the problem. But, I want to know the under the hood. I'm React noob, so could you please explain the how asynchronizing the state update can make a seperate React DOM update?

          – Hoseong Son
          Jan 1 at 12:59






          1




          1





          I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

          – Ryan Cogswell
          Jan 1 at 13:12





          I've updated my answer to explain this further. You can find more detail in some links about the React Fiber Reconciler at the end of my answer here: stackoverflow.com/questions/53974865/…

          – Ryan Cogswell
          Jan 1 at 13:12




















          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%2f53995431%2freact-compresses-rendering-causing-not-updating-components-even-if-componentdid%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

          MongoDB - Not Authorized To Execute Command

          in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

          Npm cannot find a required file even through it is in the searched directory