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.
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.