我应该在 useCallback 的依赖数组中包含 setState 吗?
Posted
技术标签:
【中文标题】我应该在 useCallback 的依赖数组中包含 setState 吗?【英文标题】:Should I include setState in useCallback's array of dependencies? 【发布时间】:2019-09-08 07:48:11 【问题描述】: const [active, setActive] = useState(false);
const onActiveChanged = useCallback(
isActive => () =>
// do something
setActive(isActive);
,
[setActive], // or just [] is okay?
);
当同时使用useState
和useCallback
(或useMemo
)时,我是否应该在依赖项数组中包含setState
?
【问题讨论】:
@AngelSalazar useState 中的更新程序方法没有被记忆或没有保留相同的引用? 我的错,根据文档“React 保证 setState 函数标识是稳定的,并且不会在重新渲染时改变。这就是为什么从 useEffect 或 useCallback 依赖列表中省略是安全的。” @AngelSalazar 感谢您的确认!我还在github.com/reactjs/reactjs.org/blob/master/content/docs/… 中找到了那部分,所以只需传递一个空数组就可以了。您可以将其作为此问题的答案,或者我将发布我自己问题的答案。 【参考方案1】:React Docs - Hooks API Reference 上也有此建议。
setState 函数用于更新状态。它接受一个新的 状态值并将组件的重新渲染排入队列。
setState(newState);
在后续重新渲染期间,第一个值 useState 返回的将始终是最近的状态 应用更新。
注意
React 保证 setState 函数的身份是稳定的,不会 更改重新渲染。这就是为什么从 useEffect 中省略是安全的 或者 useCallback 依赖列表。
【讨论】:
【参考方案2】:正如您正确暗示的那样,useCallback
的目的是memoise:
useCallback(fn, deps) 等价于 useMemo(() => fn, deps)。
至于useMemo
的用途:
您可以依赖 useMemo 作为性能优化,而不是语义保证。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
但作为一项规则,useState
在渲染之间是稳定的(即预先记忆),因此您不需要再次记忆它。
那么问题来了,您的“做某事”是否低于昂贵的计算?使用useCallback
应该不会太麻烦,但很可能是你不需要的boilerplate code,几乎可以直接使用你的setActive
函数。
const [active, setActive] = useState(false);
const onActiveChanged = useCallback(
isActive => () =>
// do something
setActive(isActive);
,
[setActive], // or just [] is okay?
);
在你的 useCallback 和其他钩子中防止不必要的依赖的另一种方法是使用functional updates。结果是你可以拥有这些:
const [active, setActive] = useState(false);
const [expensiveCalc, setExpensiveCalc] = useState(false);
const onExpensiveCalc = useCallback(
expensiveInput => () =>
const newState = doExpensiveCalc(expensiveInput);
expensiveCalc(newState);
,
[setActive], // here for completeness
);
return (<>
// expensive calculation
<button onClick=onExpensiveCalc>Do lengthy calculation</button>
// cheap calculation, using functional updates
<button onClick=() => setActive(prevBoolean => !prevBoolean)>Cheap Set Active</button>
</>)
请注意,设置状态在 onClick 中的工作方式与 nuance 有关,您应该使用箭头功能,因此您的 setActive
在单击时运行,而不是渲染。这在上面的第二个答案中显示,但没有解释。
另见:What is useState() in React?
【讨论】:
以上是关于我应该在 useCallback 的依赖数组中包含 setState 吗?的主要内容,如果未能解决你的问题,请参考以下文章
React Hook useCallback 缺少依赖项:'Id'。包括它或删除依赖数组[重复]
使用 webpack 在 Vue PWA 中包含大型 js 依赖项