Consider these two components:
function App1 () {
return <button onClick={() => null}>Click me</button>
}
function App2 () {
const fn = () => null;
return <button onClick={fn}>Click me</button>
}
Only difference is the click handler is defined inline in the first case, and extracted in a function in the latter.
I’ve always thought these snippets behave exaclty the same way.
The only way I could imagine this not being the case is if JSX transpilation alters the outputs, but it doesn’t seem the case
Today I’ve been told that in App1
the inline function is created every time the component re-renders, but this doesn’t happen in App2
. This also obtained initial confirmation by ChatGPT:
[ChatGPT]
In App1, the arrow function is directly declared inside the onClick attribute.
This means that a new function instance is created each time the component re-renders.
In App2, the arrow function fn is declared outside of the render function and then passed as a reference to the onClick attribute.
This means that the same function instance is used across re-renders.
But this seems wrong: it seems ChatGPT consider only the JSX section being part of the render function, but App2 is the render function, and is re-executed in its interety every time there’s a re-render, so recreating each time also fn
.
When I pointed this out with ChatGPT, it apologized (of course), and changed its version.
So I’m asking this here: Is any difference in these two components?
2
Answers
Never trust a robot to do a programmer’s job. :snort:
The lambda is created anew on each render in both cases. To avoid the lambda being re-created it would need to be wrapped in something like
useMemo
or moved outside of the component.i.e. they are the same
If you want to only declare your function once, you must put it outside the component
If you want to cache function definitions between re-renders, make sure to wrap it in a
useCallback
hookReference: https://react.dev/reference/react/useCallback