根据https://react.dev/reference/react/useMemo,它表示useMemo使用Object.is()函数计算deps值,因此如果deps值是非基元的,如数组或对象,useMemo将在每次渲染时计算值.

Code Sandbox

import { useMemo, useState } from "react";

export default function App() {
  const temp = { a: 1 };
  const [a, setA] = useState({ a: 1 });
  const [aa, setAA] = useState(1);

  const obj = useMemo(() => {
    console.log("obj");
    return { b: a.a };
  }, [a]);

  const obj2 = useMemo(() => {
    console.log("obj2");
    return { b: temp.a };
  }, [temp]);

  return (
    <div className="App">
      <button onClick={() => setA((prev) => ({ a: prev.a + 1 }))}>
        button {a.a}
      </button>
      <div>{obj.b}</div>
      <div>{obj2.b}</div>
      <button onClick={() => setAA((prev) => prev + 1)}>premitive {aa}</button>
    </div>
  );
}

当我单击第一个或第二个按钮时,控制台输出obj2,这是有意义的,因为变量temp是一个对象,并使用Memo计算每次呈现的值.

但是,当我单击第二个按钮时,即使变量a是对象状态,控制台也不会输出obj.

为什么会发生这种事呢?我假设第一个useMemo也计算每次呈现的值,但不知何故并非如此

推荐答案

因此,如果deps值不是像数组或对象这样的原始值,则useMemo会在每次呈现时计算值

你误解了这一点.对于非基元值,Object.is()会比较它们是否是相同的引用.所以如果你做Object.is({a: 1}, {a: 1}),它将返回false.

但在本例中,如果下一次渲染未修改,则useState()将返回相同的引用,因为单击第二个按钮不会修改a,因此当您单击第二个按钮时就是这种情况.

如果将{...a}传递给useMemo(),这将创建a的浅表克隆,则将在每次渲染时重新计算useMemo().

Reactjs相关问答推荐

替换谷歌 map api默认信息窗口与自定义

useTranslation不会在languageChanged上重新呈现组件

通过单击具有此值的按钮将值添加到数组对象键

在Reaction常量函数中未更新状态变量

如何使用皮金贴图在Reactjs中制作 map 上的点之间的线的动画?

react 挂钩-使用有效澄清

无法找出状态正在被更改的位置

带有样式的工具提示导致无法向功能组件提供参考警告

react 本机屏幕转换

在MongoDB中,如何获取最后N条记录中字段不为空或不为空字符串的数据

如何在next.js 13中仅在主页导航栏上隐藏组件?

React - 拖放 UML

如何在react 中更新子组件中的变量?

React Router v6 - 访问嵌套路由和处理手写 url 的正确方法

在 Reactjs 中状态发生变化时渲染一个新组件而不替换旧组件

将 Material UI 菜单渲染为

如何在 React 中的 Material Ui 多选中设置默认值?

为什么我从另一个组件收到错误?

React 似乎在触发另一个组件时重新渲染了错误的组件

React.js 中的页面崩溃(读取未定义的属性)