0

I found this question but it doesn't answer my specific case, because the answers are old, don't answer all my questions in this post and in that case they only pass the event variable to the function, but in my case I might want to pass a different type of value, like a string: React performance: anonymous function vs named function vs method

In React, on a function component, let's say I have a button:

return <button>Click me</button>

I want to add an onClick event to it, but instead of passing the mouse event to the function, I want to send other kinds of data. What's the correct (or even better, the most performant) pattern?

The use case would be a grid with hundreds of cells, and every cell has an onClick event. I guess that option b would be better because we're only passing a reference, right? Does modern React have some kind of optimizations for this use case?

a)

const handleClick = (value) => console.log(value);
return <button onClick={() => handleClick('hello')}>Click me</button>

b)

const handleClick = (value) => () => console.log(value);
return <button onClick={handleClick('hello')}>Click me</button>
1
  • 1
    There's very little difference between those pieces of code. Both are creating a brand new function and passing it to onClick, just A creates it inline and B creates it by calling a helper function. Use whichever you find to be easier to understand. Commented Apr 6, 2022 at 13:46

1 Answer 1

1
  1. b) unless your handleClick function returns a new function (which will act like the first example) it won't work because all you're doing is assigning the result of calling that function to the listener rather than the reference to the function.

  2. a) will work but there's a lot of documentation around to suggest that rebinding arrow functions on each render leads to poor performance.

  3. I prefer to do onClick={fn} and then define the function either within the component, or outside it, or maybe I've imported it. Either way I think it makes it more readable. But that's an opinion, and many developers have different approaches.

  4. But the main issue is: don't attach an click listener to every single one of the cells! That most likely will lead to a performance issue. Instead: a) add one listener to a containing element (table, for example), and then, using event delegation watch for events from the cells as the "bubble up" the DOM. b) Use Data attributes to attach specific data to the cells, and pick up their data in the click handler from the dataset.

So: a contrived example to show you those last points:

function Example() {

  // Because we're using event delegation
  // check to see if the element we clicked on
  // was actually a table cell, then grab the id
  // from its dataset
  function handleClick(e) {
    if (e.target.matches('td')) {
      const { id } = e.target.dataset;
      console.log(id);
    }
  }

  // One listener to rule them all
  return (
    <table onClick={handleClick}>
      <tbody>
        <tr>
          <td data-id="1">One</td>
          <td data-id="2">Two</td>
          <td data-id="3">Three</td>
        </tr>
      </tbody>
    </table>
  );

}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
table { border: 1px solid #565656; border-collapse: collapse; }
td { border: 1px solid #787878; padding: 0.3em; }
td:hover { cursor: pointer; background-color: #dfdfdf; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Sign up to request clarification or add additional context in comments.

3 Comments

Hey Andy, if you notice on pattern b I have a function that returns a function, look at this code sandbox: codesandbox.io/s/compassionate-perlman-fp3edi so in reality pattern B would work in my case. In any case, your 4th point was very interesting, thank you. Upvoted, but didn't set as the answer because it didn't answer my question
@C.Rib: I updated that first point to account for that closure issue.
I'm happy with what I've learned, thanks to you and Nicholas Tower's comment under my question. marked as accepted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.