我应该在 useCallback 的依赖项数组中包含 setState 吗?
Should I include setState in useCallback's array of dependencies?
const [active, setActive] = useState(false);
const onActiveChanged = useCallback(
isActive => () => {
// do something
setActive(isActive);
},
[setActive], // or just [] is okay?
);
同时使用 useState
和 useCallback
(或 useMemo
)时,我应该在依赖项数组中包含 setState
吗?
React Docs - Hooks API Reference 上也有对此的建议。
The setState function is used to update the state. It accepts a new
state value and enqueues a re-render of the component.
setState(newState);
During subsequent re-renders, the first value
returned by useState will always be the most recent state after
applying updates.
Note
React guarantees that setState function identity is stable and won’t
change on re-renders. This is why it’s safe to omit from the useEffect
or useCallback dependency list.
正如您正确暗示的那样,useCallback
的目的是 memoise:
useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).
至于 useMemo
的用途:
You may rely on useMemo as a performance optimization, not as a semantic guarantee.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
但作为一项规则,useState
在渲染之间是稳定的(即预先记忆),因此您不需要再次记忆它 。
那么问题来了,你的'do something'下面是一个昂贵的计算吗?使用 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 中设置状态的工作方式有点 ,您应该使用箭头功能,因此您的 setActive
是 运行单击,而不是渲染。这显示在上面的第二个答案中,但没有解释。
另请参阅:
const [active, setActive] = useState(false);
const onActiveChanged = useCallback(
isActive => () => {
// do something
setActive(isActive);
},
[setActive], // or just [] is okay?
);
同时使用 useState
和 useCallback
(或 useMemo
)时,我应该在依赖项数组中包含 setState
吗?
React Docs - Hooks API Reference 上也有对此的建议。
The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.
setState(newState);
During subsequent re-renders, the first value returned by useState will always be the most recent state after applying updates.
Note
React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.
正如您正确暗示的那样,useCallback
的目的是 memoise:
useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).
至于 useMemo
的用途:
You may rely on useMemo as a performance optimization, not as a semantic guarantee.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
但作为一项规则,useState
在渲染之间是稳定的(即预先记忆),因此您不需要再次记忆它 。
那么问题来了,你的'do something'下面是一个昂贵的计算吗?使用 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 中设置状态的工作方式有点 setActive
是 运行单击,而不是渲染。这显示在上面的第二个答案中,但没有解释。
另请参阅: