Search code examples
javascriptreactjsjsx

In React, does creating a click handler outside the JSX have any improvement on performance?


Here is an example of 2 buttons with click handlers, one function is created in the component body, the other in the JSX. Is there any performance differences?

function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <button onClick={handleClick} />
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
    </div>
  );
}

My understanding is the they are the same, and the function gets recreated on every Parent re-render. But I'm curious if I'm missing anything. I know I can use useCallback or other memoizing techniques, but this question is just purely these 2 scenarios.


Solution

  • If there is any performance difference, it will be trivial. The only difference is whether you assign the function to an intermediate variable or not. A single assignment is very very fast. Plus, after you transpile your code, minify it, and then the browser does its own optimizations, there's a chance this assignment won't even exist at all.

    I strongly recommend that you do not try to optimize at this level. Write your code for readability, and save the performance improvements for larger scale things.

    I know I can use useCallback or other memoizing techniques

    I know these weren't the question, but i suspect you may misunderstand what they do. If you wrap the function in a useCallback, you would make the example you showed very slightly slower, not faster:

    const handleClick = useCallback(() => {
      setCount(count + 1);
    }, [])
    

    With this code, you will still create a function every time you render, so you're already tied in terms of work done. That function, instead of being immediately assigned to handleClick, gets passed into useCallback, which will iterate through the dependency array doing comparisons. A function call plus a loop of comparisons is very fast, but it's slower than doing absolutely nothing.

    There is a performance benefit from useCallback, but it's not present in your example. The benefit comes when you pass your function to another piece of code. If you pass a different function each time, then that other code may need to repeat some work. For example, a component thinks its props have changed, so it must rerender; or a useEffect thinks its dependency array has changed, so it must rerun. useCallback lets you pass the same function each time, potentially skipping some work.