Reputation: 7642
I understand this works but I'm after a good explanation as to what the difference is and which one is preferable and why
what's the difference between
<Test onClick={() => myFunction()} />
and
<Test onClick={myFunction} />
is the second one always preferable ?
Upvotes: 1
Views: 85
Reputation: 5186
Typically the two have the same effect but there MAY be differences in the context of React.
The first function will have a unique new identity every time the component is rendered, the second one may have the same identity every time the component is rendered depending on what the original definition of myFunction
looks like.
Example1:
const myFunction = () => {}
// same referential identity on every render
export const Component1 = props => <Button onClick={myFunction} />
// different referential identity on every render
export const Component1 = props => <Button onClick={ () => myFunction() } />
Example2:
// different referential identity on every render
export const Component1 = props => {
const myFunction = () => {}
return <Button onClick={myFunction} />
}
// different referential identity on every render
export const Component1 = props => {
const myFunction = () => {}
<Button onClick={ () => myFunction() } />
Example3:
// same referential identity on every render
export const Component1 = props => {
const myFunction = useCallback(() => {}, [])
return <Button onClick={myFunction} />
}
// different referential identity on every render
export const Component1 = props => {
const myFunction = () => {}
<Button onClick={ () => myFunction() } />
Why does this matter? Well, when React performs the reconciliation and diffing algorithm, it will render a virtual DOM and then compare the previous virtual DOM with the new result. If the elements differ, it will switch the elements altogether in the real DOM and if attributes differ, it will just change the attributes of the corresponding existing element in the real DOM. For functions, the identity of the function is used to determine if the attribute is the same or not.
When it comes to rerendering (e.g. not the resulting changes in the DOM but the generation of the virtual DOM in React), it can also play a role if React.memo
is used:
Example 4:
const myFunction = () => {}
const MemoButton = React.memo(Button)
// does not trigger MemoButton to rerender when parent rerenders
export const Component1 = props =>
<MemoButton onClick={myFunction} />
// does trigger MemoButton to rerender when parent rerenders
export const Component1 = props =>
<MemoButton onClick={ () => myFunction() } />
There might be cases when you run into odd problem related to the above phenomenon, even though this is more likely when the identity of functions that return DOM elements are at stake, as opposed to the identity of functions used as attributes, even though I bet there is some use-case for this, even though it's hard to come up with a toy scenario.
I would not by definition prefer one of those, but it's important to understand the difference.
Upvotes: 0
Reputation: 27
they are indeed not the same, the one on the left is ot able to receive an event object. The last one can. It was confusing for me when I begun coding.
Upvotes: 0
Reputation: 1074258
It's the difference between:
const onClick = () => myFunction();
and
const onClick = myFunction;
That is, the first one creates a function (on every render) that calls myFunction
with no arguments when it (the wrapper function) is called, and uses that as the click
handler. The second just uses myFunction
as the click
handler directly, meaning it'll receive the event object from React's synthetic event system.
Avoiding unnecessary function creation is generally a good thing, and may affect whether the component you're providing the function to can avoid re-rendering or not (via React.memo
or by implementing shouldComponentUpdate
in a class
component [directly, or via PureComponent
]). (If you provide it the same function from one render to the next, maybe it can; if you provide a different function on each render, it can't.)
Upvotes: 3
Reputation: 2247
In your first case, the function passed to the onclick handler is an anonymous function which calls myFunction
inside it.
In the second case, the reference of myFunction
is directly passed to the onclick handler.
You should prefer the second solution unless you have to add something else than myFunction()
in the anonymous function.
Note that creating an anonymous function allocates memory for the closure scope of that function, so if the role of that closure is just to wrap another one then you lose memory performance for nothing...
Upvotes: 0
Reputation: 13245
They're the same in this case, except myFunction
doesn't get the click event since you don't pass it in. But say you had a generic function and you wanted to pass in more arguments to myFunction
, when you would use the first one and give it extra arguments.
Preference for first or second without extra args or needing click event is a matter of opinion, but the first one adds unnecessary complexity.
Upvotes: 0