简体   繁体   English

使用 ref 防止来自 useCallback 的经常变化的值

[英]Use of ref to prevent often-changing value from useCallback

In the Reach Hooks FAQ section "How to read an often-changing value from useCallback?"在 Reach Hooks 常见问题解答部分“如何从 useCallback 中读取经常变化的值?” there is an example:有一个例子:

function Form() {
  const [text, updateText] = useState('');
  const textRef = useRef();

  useEffect(() => {
    textRef.current = text; // Write it to the ref
  });

  const handleSubmit = useCallback(() => {
    const currentText = textRef.current; // Read it from the ref
    alert(currentText);
  }, [textRef]); // Don't recreate handleSubmit like [text] would do

  return (
    <>
      <input value={text} onChange={e => updateText(e.target.value)} />
      <ExpensiveTree onSubmit={handleSubmit} />
    </>
  );
}

I was so confused:我很困惑:

  • Instead of useCallback updating the function each time the text changes, this code moves it to textRef in useEffect.每次文本更改时,useCallback 都不会更新 function,而是将此代码移动到 useEffect 中的 textRef。 But isn't that the same because the callback function doesn't change but you still need 1 step to update the value in useEffect?但是这不一样吗,因为回调 function 没有改变,但您仍然需要 1 步来更新 useEffect 中的值?
  • Why is textRef in the dependency array?为什么 textRef 在依赖数组中? Isn't textRef a reference which doesn't change between renders? textRef 不是在渲染之间不会改变的引用吗? We always receive the same reference so wouldn't it be the same as inputting an empty array?我们总是收到相同的引用,所以它与输入一个空数组不一样吗?

instead of useCallback update the function each time the text change, this code move it to textRef in useEffect but isn't that the same because the callback function doesn't change but you still need 1 step to update the value in useEffect?而不是 useCallback 每次文本更改时更新 function,此代码将其移动到 useEffect 中的 textRef 但不一样,因为回调 function 不会改变,但您仍然需要 1 步来更新 useEffect 中的值?

With the useRef setup, each render re-runs useEffect but handleSubmit stays the same.使用useRef设置,每个渲染都会重新运行useEffecthandleSubmit保持不变。 In a normal setup, each render would re-run useCallback and handleSubmit would be a new reference to a new function.在正常设置中,每个渲染都将重新运行useCallback并且handleSubmit将是对新 function 的新引用。 I can see why on the surface this seems like the same amount of work.我可以明白为什么从表面上看这似乎是相同的工作量。

The benefits of the ref approach are what other re-renders happen based on a re-rendering of Form . ref 方法的好处是基于Form的重新渲染发生的其他重新渲染。 Each time the value of text changes, the parent Form re-renders and the child input re-renders since it takes text as a prop.每次text的值发生变化时,父Form会重新渲染,而子input会重新渲染,因为它将text作为 prop。 ExpensiveTree does not re-render because its prop handleSubmit maintains the same reference. ExpensiveTree不会重新渲染,因为它的 prop handleSubmit保持相同的引用。 Of course the name ExpensiveTree is designed to tell us that we want to minimize re-rendering of that component since it is computationally expensive.当然, ExpensiveTree这个名称旨在告诉我们,我们希望尽量减少该组件的重新渲染,因为它的计算成本很高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM