【问题标题】:Does useMemo hooks in React.js also memoizes object reference as well?React.js 中的 useMemo 钩子是否也可以记住对象引用?
【发布时间】:2021-09-06 14:05:59
【问题描述】:

这是关于 React.js 中 useMemo 钩子的常见解释

useMemo(compute, dependencies) invokes compute, memoizes the calculation result, and returns it to the component.

If during next renderings the dependencies don’t change, then useMemo() doesn’t invoke compute but returns the memoized value.

- Dmitri Pavlutin

但是,我看到了 useMemo 钩子的示例,它返回如下所示的数组。

React.useMemo(() => [1, 2, 3], []);

如您所见,useMemo 返回一个数组,该数组在 Javascript 中被视为对象。

这令人困惑。我认为 useMemo 钩子的用法是用于记忆计算值。

所以我做了一个小测试来弄清楚 useMemo with object 是如何工作的

const Child = React.memo(({ obj }) => {

  console.log('this is child component')

  return <div>Child Component</div>
})

const App = () => {
  const [toggle, setToggle] = React.useState(false)

  const memoObj = React.useMemo(() => { return { bar: 'foo' } }, [])

  return (
    <div>
      <button onClick={() => setToggle(!toggle)}>test</button>
      <Child obj={memoObj} />
    </div>
  );
}

memoObj 没有被 useMemo 包装时,每当我点击 test 按钮时,我都可以在控制台中看到来自 Child 组件的消息。

另一方面,当 memoObj 被钩子包裹时,消息仅在 Child 组件第一次渲染时显示。

是不是说useMemo不仅可以memoize计算值,还可以memoize对象的引用?

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    没错,useMemo 将始终保留对上次渲染的对象的引用,而 useCallback 保留上次渲染的函数(也是对象)的引用

    您的示例也是了解 useMemo 工作原理的好方法!

    您也可以为 useCallback 创建相同的示例,这将给出相同的行为

    const Child = React.memo(({ obj }) => {
       console.log('this is child component');
    
       return <div>Child Component</div>;
    });
    
    const App = () => {
       const [toggle, setToggle] = React.useState(false);
    
       const useCallbackObj = React.useCallback(() => {
          console.log('callback is called!');
       }, []);
    
       return (
          <div>
             <button onClick={() => setToggle(!toggle)}>test</button>
             <Child obj={useCallbackObj} />
          </div>
       );
    };
    

    【讨论】:

      【解决方案2】:

      是不是说useMemo不仅可以memoize计算值,也可以memoize一个对象的引用?

      当然是的,并且在需要重新渲染之前不会重新渲染记忆化的组件(就像某些事情发生了变化一样)。

      但你必须记住:

      默认情况下,它只会对 props 对象中的复杂对象进行浅层比较。

      所以

      如果您想控制比较,您还可以提供自定义比较函数作为第二个参数。

      function MyComponent(props) {
        /* render using props */
      }
      function areEqual(prevProps, nextProps) {
        /*
        return true if passing nextProps to render would return
        the same result as passing prevProps to render,
        otherwise return false
        */
      }
      export default React.memo(MyComponent, areEqual);
      

      React 是这么说的。

      【讨论】:

      • 错误答案。他要求 useMemo 钩子。 useMemo 不会进行浅比较,如果 ref 对象发生变异,它将再次运行。如果要优化 useMemo,可以使用 useMemo 依赖数组中的对象属性。
      猜你喜欢
      • 1970-01-01
      • 2019-08-20
      • 2022-01-15
      • 2021-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多