简体   繁体   中英

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?" 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. 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?
  • Why is textRef in the dependency array? Isn't textRef a reference which doesn't change between renders? 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?

With the useRef setup, each render re-runs useEffect but handleSubmit stays the same. In a normal setup, each render would re-run useCallback and handleSubmit would be a new reference to a new 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 . 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. ExpensiveTree does not re-render because its prop handleSubmit maintains the same reference. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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