为什么 useMemo 不记忆值

时间:2021-04-29 06:04:10

标签: reactjs react-hooks

我有一个简单的例子:

import { useMemo, useState } from "react";
import "./styles.css";

const calc = (n) => (
  Math.random()
)

export default function App() {
  const [n, setN] = useState(1);
  const r = useMemo(() => 
    calc(n)
  , [n])
  return (
    <div className="App">
      <input onChange={e => setN(e.target.value)}/><br/>
      <strong>useMemo: {r}</strong><br/>
    </div>
  );
}

为什么对于相同的依赖项 n,它在 r 中显示不同的结果? AFAIK,它应该被记住......

3 个答案:

答案 0 :(得分:4)

来自docs

<块引用>

传递一个“创建”函数和一组依赖项。 useMemo 只会在依赖项之一发生变化时重新计算记忆值。这种优化有助于避免每次渲染时进行昂贵的计算。

示例:

n = 1时,r变成0.1234

现在当 n = 2 时,r 变成 0.2345。 (依赖项已更改,因此将重新计算)

再次当 n = 1 时,r 变成 0.1930。 (依赖项已更改,因此将重新计算)


因此,useMemo 按预期工作。但是您可能需要不同的工具来完成您想要做的事情(可能类似于 Map / Object)。请记住,useMemo 是一种性能优化工具(它不是键值映射)。

答案 1 :(得分:1)

因为 useMemo 会在依赖项改变时再次调用。当您更改输入时,setN 将调用,因此状态 n 将更改。然后 useMemo 中的函数将调用并返回 r

的新值

答案 2 :(得分:1)

<input onChange={e => setN(e.target.value)}/><br/>

e.target.value 的类型是 String。您使用数字 1 启动状态,这是数字类型。

因此,当您在键盘上键入相同的初始值时,您实际上得到的值是 "1"

"1" !== 1 起,setState 触发更改。

如果你改变了,

<input onChange={e => setN(e.target.value)}/><br/>

<input onChange={e => setN(Number(e.target.value))}/><br/>

现在尝试插入与 1 相同的值,您将看到它不会触发组件更新。但是现在你应该小心,如果你在键盘上输入一个非数字值,你会得到 Null 作为 Number(e.target.value) 的返回。这将导致不更新状态,

<块引用>

使用 null 调用 setState 不再触发更新。这允许 如果要重新渲染,您可以在更新程序功能中决定。