8

我不明白为什么useCallback每次更新一个部门时总是返回一个新的参考。React.memo()它导致许多本可以避免的重新渲染。

如果有的话,这个实现的问题是useCallback什么?

export function useCallback(callback) {

    const callbackRef = useRef();

    callbackRef.current = callback;

    return useState(() =>
        (...args) => callbackRef.current(...args)
    )[0];

}

使用它而不是内置实现肯定会对性能产生重大的积极影响。

自己的结论:

只要您了解其含义,就没有理由不使用使用 ref 的实现而不是内置的setTimeout,即,正如@Bergy 所指出的,您不能存储回调以供以后使用(例如,在之后)并期望回调具有与同步调用它相同的效果。
然而,在我看来,这是首选行为,因此没有缺点。

4

2 回答 2

5

如果有的话,这个实现的问题是useCallback什么?

我怀疑当有人存储对您的回调的引用以供以后使用时,它会产生意想不到的后果,因为它会改变它正在做的事情:

const { Fragment, useCallback, useState } = React;

function App() {
  const [value, setValue] = useState("");
  const printer = useCallback(() => value, [value]);
  return <div>
    <input type="text" value={value} onChange={e => setValue(e.currentTarget.value)} />
    <Example printer={printer} />
  </div>
}

function Example({printer}) {
  const [printerHistory, setHistory] = useState([]);
  return <Fragment>
    <ul>{
      printerHistory.map(printer => <li>{printer()}</li>)
    }</ul>
    <button onClick={e => setHistory([...printerHistory, printer])}>Store</button>
  </Fragment>
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://unpkg.com/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

(当然,在这个简化的演示中,printer回调只不过是对value自身的无用闭包,但您可以想象一个更复杂的情况,即可以选择一个单独的历史条目并希望在回调中使用复杂的按需计算)

使用 native useCallback,存储在 中的函数printerHistory将是不同值的不同闭包,而在您的实现中,它们都是引用最新useCallback参数的同一个函数,并且只在每次调用时打印当前值。

于 2021-01-28T13:47:42.323 回答
0

useCallback 和 useMemo 的用例是不同的。您说过 useCallback 返回回调的记忆版本,仅当其中一个依赖项发生更改时才会更改。结果,它根据依赖关系的变化重新渲染组件。但是 useMemo 只保存可变值。通常,我们使用 useCallback 来处理事件处理程序。例如,假设当您单击按钮时,会显示按钮单击的计数。在这种情况下,单击事件是使用 useCallback 实现的。

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

要在单击按钮时获取新的增加计数值并显示其值,需要重新渲染。再说一遍,useCallback 和 useMemo 的用例取决于目的。

于 2021-01-28T13:50:21.313 回答