Home  >  Q&A  >  body text

How does useCallback help code run faster?

<p>So it is said that useCallback can cache a function, I think the intention is to make the code run faster. </p> <p>For example, if I have: </p> <pre class="brush:js;toolbar:false;"> const handleChange = (ev) => { setMsg(ev.target.value); }; </pre> <p>I could also change it to: </p> <pre class="brush:js;toolbar:false;"> const handleChange = useCallback((ev) => { setMsg(ev.target.value); }, []); </pre> <p>The function is now cached. However, does this function need to be created when the component re-renders anyway? </p> <p>To test it, I changed it to an IIFE so that the function was being output from it, and it would print out that the function was being output. </p> <p>See: https://codesandbox.io/s/jolly-nightingale-zxqp8k</p> <p>So every time you type something in the input box, a new function will be output, as shown in the console. This means that the IIFE will be executed every time, which also means that the function literal will be converted to a function object every time, even if it is not an IIFE. So how does this help code run faster? </p>
P粉924915787P粉924915787398 days ago446

reply all(1)I'll reply

  • P粉834840856

    P粉8348408562023-08-19 00:29:53

    Yes, this is correct. Each render creates a new function, which is then replaced by the cached function.

    The speedup is not due to skipping the step of creating the function, but because other code is able to skip their own work. This is because if they are passed the same function every time, they know that nothing relevant has changed.

    For example, if you need to pass handleChange to the dependency array of useEffect, it is very important to pass a stable reference every time, otherwise the effect will be passed every time it is rendered. Rerun:

    useEffect(() => {
      // ... 使用handleChange做一些事情
    }, [handleChange]);

    Alternatively, if handleChange is passed as a prop to a component and the component wants to skip rendering using React.memo. Rendering can be skipped only when props have not changed:

    const Parent = () => {
      const handleChange = useCallback((ev) => {
        setMsg(ev.target.value);
      }, []);
      return <Child handleChange={handleChange}/>
    }
    
    const Child = React.memo(({ handleChange }) => {
      // ... 使用handleChange做一些事情
    })

    reply
    0
  • Cancelreply