代码之家  ›  专栏  ›  技术社区  ›  Keith Brewster

什么时候不应该使用React memo?

  •  8
  • Keith Brewster  · 技术社区  · 7 年前

    16.6.0 最近我很喜欢 反应备忘录 ,但我找不到任何最适合实现它的场景。

    React文档( https://reactjs.org/docs/react-api.html#reactmemo )不要仅仅把它放在你所有的功能组件上就暗示了什么。

    对绩效有负面影响?

    这样的情况似乎是一个明显的实施选择:

    // NameComponent.js
    import React from "react";
    const NameComponent = ({ name }) => <div>{name}</div>;
    export default React.memo(NameComponent);
    
    // CountComponent.js
    import React from "react";
    const CountComponent = ({ count }) => <div>{count}</div>;
    export default CountComponent;
    
    // App.js
    import React from "react";
    import NameComponent from "./NameComponent";
    import CountComponent from "./CountComponent";
    
    class App extends Component {
      state = {
        name: "Keith",
        count: 0
      };
    
      handleClick = e => {
        this.setState({ count: this.state.count + 1 });
      };
    
      render() {
        return (
          <div>
            <NameComponent name={this.state.name} />
            <CountComponent count={this.state.count} />
            <button onClick={this.handleClick}>Add Count</button>
          </div>
        );
      }
    }
    

    因为 name 记忆化

    但如果道具经常更换,情况会怎样呢?
    如果我添加了另一个按钮,它改变了状态中的其他内容并触发了重新渲染,那么包装是否有意义呢 CountComponent 备忘录

    只要所有的东西都保持纯净,有没有一种情况不能用React Memo包装一个功能组件?

    0 回复  |  直到 7 年前
        1
  •  38
  •   Ntokozo Zwane    6 年前

    所有react组件实现 shouldComponentUpdate() 方法。默认情况下(组件) React.Component React.memo 用于功能部件或扩展 React.PureComponent 对于类组件)是 方法-对状态和道具进行简单的比较。

    documentation 在组件生命周期方法上, shouldComponentUpdate()

    考虑到这一点,记忆一个组件

    为了回答您的问题,我不认为有一个明确的规则,当您应该或不应该memoize组件,但我认为同样的原则应该适用于决定是否应该覆盖 :通过建议的 profiling tools

        2
  •  27
  •   Jalal    5 年前

    你应该经常使用 React.memo 从字面上讲,比较组件返回的树总是比比较一对 props 属性

    反应备忘录 原本打算内置到核心功能组件中,但由于失去向后兼容性,默认情况下不使用(因为它表面上比较了对象,而且您可能正在使用组件中子对象的嵌套属性)=)

    就是这样,这就是React不自动使用备忘录的唯一原因

    事实上,他们可以制作17.0.0版本,这将破坏向后兼容性,并使 反应备忘录 React.deepProps

    别听理论家的话,伙计们=)规则很简单:

    如果您的组件使用深度比较道具,那么不要使用memo,否则请始终使用它,比较两个对象总是比调用 React.createElement()

    理论家谈论他们自己不知道的东西,他们没有分析react代码,他们不理解FRP,他们不理解他们的建议=)

    如果您的组件正在使用 children 道具, 行不通,因为 儿童

        3
  •  16
  •   ford04    6 年前

    是否会出现对绩效产生负面影响的情况?

    React.memo .

    在许多情况下不需要。要尝试使用性能关键型组件,请先进行一些度量,添加备忘录,然后再次进行度量,以确定增加的复杂性是否值得。

    你的费用是多少 反应备忘录 ?

    记忆化的组件将旧的与新闻道具进行比较,以决定是否重新渲染- .
    在父级中的props/state更改之后,普通组件不关心,只渲染。

    shallowEqual 在中调用的实现 updateMemoComponent .

    React memo ?

    反应备忘录 负面影响:

    1. 组件重新渲染的成本很低

    广告1:在这种情况下, 反应备忘录 无法阻止重新渲染,但必须进行其他计算。
    ad2:对于一个“简单”的组件来说,在渲染、协调、DOM更改和副作用成本方面增加的比较成本是不值得的。
    广告3:道具越多,计算越多。你也可以通过一个更复杂的 custom comparer .

    何时补足 反应备忘录 ?

    它只检查道具,不检查内部的上下文更改或状态更改。 如果已记忆的组件具有非原语 children . useMemo 可以补充 memo 这里,比如:

    // inside React.memo component
    const ctxVal = useContext(MyContext); // context change normally trigger re-render
    return useMemo(() => <Child />, [customDep]) // prevent re-render of children
    
        4
  •  6
  •   andraaspar    6 年前

    The same question answer by markerikson on the React GitHub issue tracker . 这比这里的答案更有说服力。

    我认为同样的一般性建议也适用于 React.memo 就像它为 shouldComponentUpdate PureComponent props.children ). 所以,不要把所有东西都自动包装起来。查看应用程序在生产模式下的行为,使用React的评测构建和DevTools profiler查看瓶颈所在,并战略性地使用这些工具优化组件树的某些部分,这些部分实际上将从这些优化中受益。

        5
  •  2
  •   Michael    7 年前

    我认为简单的答案是: 反应备忘录 React.PureComponent组件 不需要对组件进行分类。

    import React, { memo } from 'react';
    
    const Component = () => {
      debugger;
      return (
        <div>Hello World!</div>
      );
    };
    
    const MemoComponent = memo(() => {
      debugger;
      return (
        <div>Hello World!</div>
      );
    });

    如果你使用 Component 作为更新容器的子组件,父组件每次更新时都会重新呈现(调试器每次都会触发)。 另一方面,如果你使用 MemoComponent 它不会重新呈现(调试器只会在第一次呈现时触发)。

        6
  •  1
  •   Zeena    6 年前

    这样做的目的是避免使用回忆录,因为数据可能会经常发生变化。如博客中所述,这还包括依赖于此类数据类型的回调。例如函数,例如

    <Foo onClick={() => handle(visitCount)}/>

    https://dmitripavlutin.com/use-react-memo-wisely/

        7
  •  -3
  •   Taylor Belk    6 年前

    请记住,传递给usemememo的函数在呈现期间运行。不要在那里做任何渲染时通常不会做的事情。例如,副作用属于useEffect,而不是useMemo。

    您可以将useMemo作为性能优化,而不是语义保证。将来,React可能会选择忘记一些以前记忆的值,并在下次渲染时重新计算它们,例如为屏幕外组件释放内存。编写代码,使其在没有usemememo的情况下仍能工作,然后添加代码以优化性能(在极少的情况下,当一个值不能被重新计算时,您可以延迟初始化一个ref。)“

    https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies