DEV Community

Dinesh Pandiyan
Dinesh Pandiyan

Posted on • Updated on

React — Access custom params in handlers the right way

TL;DR - You can access render time values in handlers without having to use anonymous arrow functions. Hint — leverage data attributes.

React is great in so many aspects and it gives us the freedom to do things in different ways by being less opinionated (or non opinionated).

In recent days, especially after the release of hooks, the community has been fussing around a lot on reference equality and how anonymous arrow functions in renders are not good for performance.

We are not going to deep dive into why or how using arrow functions during render affects the performance (or it does not). Here are two contrasting tweets for context.

When

We mostly use arrow functions during render only to pass custom parameters to event handlers.

For example, this is a common use case —

const MyComp = () => {
  const handleClick = (e, id) => {
    // handle click and use id to update state
  }

  // id comes from state
  return (
    <div onClick={(e) => handleClick(e, id)}>Hello World!</div>
  )
}
Enter fullscreen mode Exit fullscreen mode

How

Instead of using an anonymous arrow function here, we could leverage data attributes and access values from the event object.

const MyComp = () => {
  const handleClick = (e) => {
    const id = e.target.dataset.id
    // handle click and use id to update state
  }

  // id comes from state
  return (
    <div data-id={id} onClick={handleClick}>Hello World!</div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Advantages

This approach has a lot of advantages —

  • You can memoize the callback pretty easily if needed.
const MyComp = () => {
  // id comes from state
  const handleClick = React.useCallback((e) => {
    const id = e.target.dataset.id
    // handle click and use id to update state
  }, [id])

  return (
    <div data-id={id} onClick={handleClick}>Hello World!</div>
  )
}
Enter fullscreen mode Exit fullscreen mode
  • You don't create a new function during component render which saves additional computation cost during vdom diffing.

  • If child components that use React.memo take this handler as a prop, you don't have to write custom areEqual method to circumvent referential integrity issues with anon arrow functions.

Keep in mind that all data attributes return String values even if you pass in other primitive types. So it's a good practice to coerce your value while extracting from dataset.

const id = e.target.dataset.id // this will be String

const id = Number(e.target.dataset.id) // convert to type if needed
Enter fullscreen mode Exit fullscreen mode

I have created a codesandbox to demonstrate how it works — Custom Params In Handlers

You are amazing! Have a great day! ⚡️

Latest comments (7)

Collapse
 
kioviensis profile image
Max Tarsis

it's just awesome
thx a lot, man

Collapse
 
wmoore98 profile image
William Moore

I like it. Seems like a simple, down and dirty way to avoid using anonymous functions when there isn't a better answer. There are plenty of places where this would have been handy. Thanks!

Collapse
 
joeattardi profile image
Joe Attardi

This is a really cool idea! I am currently using anonymous arrow functions in my components/apps, maybe I'll refactor and use this approach.

Collapse
 
sunnysingh profile image
Sunny Singh

I don't think that I would like to place data that I already have in the DOM and then retrieving it again from the DOM, but there could definitely be some use cases for this approach. Thanks for sharing!

Collapse
 
guico33 profile image
guico33

The example given isn't relevant. If the id is coming from the props object, one can simply read it from through the closure in which case passing the data as an id to the html element and reading it from the event is useless.

If performance is a concern, one can also create a new component, pass the the necessary data as a prop and define the callback in the child.
I guess the described method could be useful for optimisation when dealing with third-party components though.

Collapse
 
flexdinesh profile image
Dinesh Pandiyan

The example was to give an idea that values can be stored as data attributes. I'll update the example to access state values so it's obvious.

Collapse
 
irreverentmike profile image
Mike Bifulco

So simple - but perfectly effective. Nice!