【问题标题】:React Global MemoizationReact 全局记忆
【发布时间】:2020-09-19 02:58:58
【问题描述】:

我有以下 React 测试应用:

class MemoTestApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    	showOverlay: false,
    }
  }
  
  render() {
    return (
      <div>
        <div>
          <MemoComponent str="Hello World" />
        </div>
        <div>
          <input type="button" onClick={() => this.setState({showOverlay: true})} value="Show Overlay"/>
        </div>
        {this.state.showOverlay && (
          <div className="overlay">
            <h2>Overlay</h2>
            <MemoComponent str="Hello World" />
          </div>
        )}
      </div>
    )
  }
}

const Component = (props) => {
  console.info('render ' + props.str);
  return <div>{props.str}</div>;
}

const MemoComponent = React.memo(Component);

ReactDOM.render(<MemoTestApp />, document.querySelector("#app"))
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
  position: relative;
  min-height: 200px;
}

.overlay {
  position: absolute;
  padding: 20px;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

如您所见,有一个记忆功能组件,它使用相同的道具渲染两次。第一次渲染立即进行,第二次在用户按下按钮后进行。

但是,正如您在控制台中看到的那样,组件确实被渲染了两次。 React.memo 阻止对组件的第一个实例进行第二次渲染,但第二个实例似乎“现在知道”该组件​​已经使用给定的 props 进行了渲染。

有没有办法让记忆化“全局化”,即渲染的输出在组件的不同实例之间共享?

React.memo默认不是全局的是什么原因?

【问题讨论】:

  • 您的实际目标是只有一个 MemoComponent 实例并在切换覆盖时在 React 树中移动它吗?
  • @ford04 不,这不是我的目标(但可能是我的“全局记忆”也有意义的场景)。我一般会问,如果相同的组件出现在 UI 的不同位置,可能使用相同的道具,那么为什么需要渲染两次?即,为什么记忆是本地的而不是全局的?

标签: reactjs memoization


【解决方案1】:

简短回答:组件是可重复使用的,这是设计使然。

它们可能有自己的状态,例如计数器。或者它们有副作用,例如自己的间隔,根据 DOM 节点的自定义逻辑。

因此,它们必须是单独的“实例”,具体取决于它们在 DOM 上的位置(父节点、索引或key),并单独呈现。然后将结果按组件“实例”进行记忆。

【讨论】:

  • 谢谢,但这是一个功能组件。功能组件的全部意义在于它是无状态的(不是在谈论钩子)并且没有副作用。所以我看不出为什么 memoization 不应该在全球范围内工作。
  • 我认为好处不会超过优化成本。这种优化应该如何工作? React 需要检查组件是否使用钩子,以及内部组成的任何组件是否遵循相同的规则。由于“全局组件”仍然可能因为不同的 props 而有所不同,因此这样的全局缓存需要跟踪 props 并管理缓存大小。另一方面,适用于全局缓存(根据给定规则)的简单组件的百分比非常小,恕我直言,具有相同道具的许多实例的概率也很小。
  • 我明白你的第二点。用例大多是边缘情况。但是,据我了解,所有必要的成分都已经存在。为了使 memoization 起作用,React 已经需要跟踪 props 并管理缓存大小。缓存已经存在。我只是在问,为什么记忆缓存不是全局的?我不明白为什么它应该更有效或更容易在本地实施。
猜你喜欢
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2022-01-17
  • 1970-01-01
  • 2014-05-11
  • 2017-11-10
  • 2021-12-23
相关资源
最近更新 更多