我有一个简单的例子:
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,它应该被记住......
答案 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 不再触发更新。这允许 如果要重新渲染,您可以在更新程序功能中决定。