React压缩渲染,即使componentDidUpdate调用

时间:2019-01-01 12:28:19

标签: javascript reactjs redux react-redux

React父组件渲染过程会自动压缩子组件的渲染。对于大多数应用程序而言,它可以提高性能,但是这种情况可能是一个严重的问题。

我有2个组成部分:

  1. 文件列表侧栏组件
  2. 文本编辑器组件(我现在正在使用Slate)

两个组件是Home组件的子组件。

当用户单击侧边栏项目时,它应该:

  1. 突出显示所选项目
  2. 通过阅读文本文件设置新的编辑器状态

第二步可能是瓶颈。这里的问题是,React愚蠢地完全压缩了分开的两个操作。 这导致用户单击后无法立即看到突出显示的项目!用户必须等待读取文件并设置新的编辑器状态,然后,项目才能突出显示。

这种延迟严重影响了用户体验。您是否曾经使用文本编辑器在约500毫秒后响应您的点击?该程序看起来“慢一些”。

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

这是componentDidUpdate。这将更新编辑器状态。

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!

日志在componentDidUpdate 21:29:18.356处显示,但实际的HTML DOM尚未更新。它会在21:29:18.678 Home.js:44 componentDidUpdate!之后自动更新DOM。'

如何分隔两个componentDidUpdates,以分别更新DOM?

1 个答案:

答案 0 :(得分:0)

我认为您应该可以通过异步触发第二次更新来解决此问题:

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);
    }
  }

我实际上并没有尝试过,因此对于语法方面的问题,我深表歉意。

通常,React在做什么是可取的-当一个状态更新立即触发另一状态更新时,不要浪费时间两次更新DOM。当两个更新都很快时,这可以避免DOM闪烁。

React之所以能够做到这一点,是因为它将工作分为两个阶段

  • 渲染/协调阶段,其中React确定了下次DOM更新时应更改的内容
  • 提交阶段,其中这些更新实际上应用于DOM

当渲染触发另一个渲染时,React将推迟到提交阶段,并为一次提交批处理DOM更新。上面的setTimeout将导致状态更新一直等到第一次更新的提交阶段之后。

我认为未来围绕异步模式的React功能将提供更好的方式来处理这种情况,其中一个更新为高优先级,另一个更新为低优先级。