Red Baron
Red Baron

Reputation: 7642

what's the difference between these two functions in react?

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

Answers (5)

fast-reflexes
fast-reflexes

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

Jordy dev
Jordy dev

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

T.J. Crowder
T.J. Crowder

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

Peterrabbit
Peterrabbit

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

Samathingamajig
Samathingamajig

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

Related Questions