为什么 `useCallback` 不能始终返回相同的引用?

8 浏览
0 Comments

为什么 `useCallback` 不能始终返回相同的引用?

我不明白为什么每次更新依赖项时,useCallback 总是会返回一个新的引用。这导致了很多次重新渲染,而 React.memo() 可以避免这种情况。\n对于这个 useCallback 的实现,是否存在任何问题?\n

export function useCallback(callback) {
    const callbackRef = useRef();
    callbackRef.current = callback;
    return useState(() =>
        (...args) => callbackRef.current(...args)
    )[0];
}

\n与内置实现相比,使用这个实现确实对性能有显著的积极影响。\n

个人结论:

\n只要你意识到了其中的影响,即如 @Bergy 所指出的,无法存储一个回调以供稍后使用(例如在 setTimeout 之后),并期望回调具有与同步调用相同的效果,那么使用引用来实现没有任何不好的地方。
\n但在我看来,这是首选的行为,因此没有缺点。\n

更新:

\nReact 正在引入一个内置的 hook,可以做到这一点。它将被称为 useEvent

0
0 Comments

问题的出现原因是因为useCallback不能始终返回相同的引用,这是由其工作原理决定的。useCallback根据依赖项的变化返回一个记忆化的回调函数,只有当依赖项发生变化时,它才会重新渲染组件。但是useMemo只能保存可变的值。

要解决这个问题,可以使用useMemo来保存回调函数的引用,而不是使用useCallback。由于useMemo可以保存可变的值,因此可以确保每次渲染时返回相同的引用。下面是一个示例:

const [count, setCount] = useState(0);
const handleClick = useMemo(() => {
  return () => {
    setCount(count + 1);
    console.log(count + 1);
  };
}, [count]);

通过使用useMemo,我们将回调函数作为一个函数表达式返回,并将其传递给useMemo的依赖项数组。这样,每当count发生变化时,useMemo都会重新计算回调函数,并返回一个新的函数引用。这确保了每次渲染都返回相同的引用,从而避免了useCallback不能始终返回相同引用的问题。

总结一下,尽管useCallback和useMemo的用例不同,但我们可以使用useMemo来解决useCallback不能始终返回相同引用的问题。通过使用useMemo保存回调函数的引用,我们可以确保每次渲染时返回相同的引用,从而避免不必要的重新渲染。

0
0 Comments

为什么`useCallback`不能始终返回相同的引用?

问题的出现原因:

在上述代码示例中,使用自定义的`useCallback`实现,会导致存储在`printerHistory`中的函数引用始终指向最新的`useCallback`参数,而不是独立的闭包。这会导致在每次调用时,所有函数都只打印当前的`value`值,而不是对应的历史值。这可能会影响到存储引用以供稍后使用的情况。

解决方法:

为了解决这个问题,可以使用原生的`useCallback`来确保每个函数都是独立的闭包。这样可以保证存储在`printerHistory`中的函数引用都是不同的,并且在每次调用时都会打印对应的历史值。

这个问题的出现说明了自定义的`useCallback`实现与原生的`useCallback`在处理函数引用时存在差异。在某些情况下,使用自定义实现可能会导致意外的结果。因此,为了确保代码的可靠性和一致性,建议使用原生的`useCallback`来处理函数引用。

补充说明:

在实际开发中,可能会遇到更复杂的场景,例如需要选择历史记录条目并在回调函数中进行复杂的计算。在这种情况下,使用原生的`useCallback`可以更好地满足需求,因为它可以确保每个函数都是独立的闭包,并且可以根据需要执行复杂的计算或副作用。

通过对比自定义的`useCallback`实现和原生的`useCallback`,我们可以看到自定义实现可能导致函数引用的不一致性,而原生实现可以保证每个函数都是独立的闭包。因此,在使用`useCallback`时,建议使用原生的实现来确保代码的可靠性和一致性。

原文内容来源:https://stackoverflow.com/questions/61522784

0