你使用useState
的初始值作为函数是什么情况?
与仅传递值有什么区别吗?
例如
const [state, setState] = useState(() => someValue)
当您希望该初始状态的计算只发生一次时,可以使用它。
因为如果你使用表达式来代替说:
const [state, setState] = useState(compute());
React 保存compute()
的初始结果一次,并在下一次渲染时忽略它。但是compute
函数仍然在每次渲染时被调用。这可能是浪费。
如果改为传递函数,则仅调用该函数一次。
从文档中:
const [state, setState] = useState(initialState);
初始状态参数是初始呈现期间使用的状态。 在随后的渲染中,它被忽略。如果初始状态为 昂贵的计算结果,您可以提供一个函数 相反,它将仅在初始渲染上执行
const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState; });
此外,如果您将函数作为参数传递给useState
,就像问题所问的那样,它必须满足某些要求:
如果将函数作为
initialState
传递,则该函数将被视为初始值设定项函数。它应该是纯的,应该不带任何参数,并且应该返回任何类型的值。React 会在初始化组件时调用你的初始值设定项函数,并将其返回值存储为初始状态。
如果你想使用useState 的初始值作为函数,你需要使用 currying :
const [state, setState] = useState(() => () => someValue);
这是因为在文档中,useState 执行提供的函数并将其结果视为初始值。 使用咖喱,返回() => someValue
并被视为初始值。
包装函数的计算量较少的原因是,当 props 发生变化时,react 会重新运行组件函数。如果 useState(( 内部有像useState(heavyComputation())
这样的计算,JavaScript 将运行 heavyComputing((,但在useState(()=>heavyComputation())
中,JavaScript 不会运行 heavyComputing((,而是会传入 curried 函数,并且 useState 知道不会重新运行这个函数。
正常
渲染 1:useState(heavyComputation()) //JavaScript calls heavyComputation
渲染 2:useState(heavyComputation()) //JavaScript calls heavyComputation
渲染 3:useState(heavyComputation()) //JavaScript calls heavyComputation
。
包装在函数中(柯里(
渲染 1:useState(()=>heavyComputation()) //useState() calls heavyComputation
渲染 2:useState(()=>heavyComputation()) //useState() uses the value from the previous render so heavyComputation() is not called
渲染 3:useState(()=>heavyComputation()) //useState() uses the value from the previous render so heavyComputation() is not called
。
当我们有一些繁重的计算来初始化状态时,我们应该使用该函数。这是状态的延迟初始化。这是一篇关于 kentcdodds 的反应状态延迟初始化的写得很好的博客。