React — Access custom params in handlers the right way
Dinesh Pandiyan

Dinesh Pandiyan @flexdinesh

Joined:
Nov 14, 2017

React — Access custom params in handlers the right way

Publish Date: Jun 6 '19
62 7

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! ⚡️

Comments 7 total

  • Mike Bifulco
    Mike BifulcoJun 6, 2019

    So simple - but perfectly effective. Nice!

  • guico33
    guico33Jun 6, 2019

    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.

    • Dinesh Pandiyan
      Dinesh PandiyanJun 6, 2019

      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.

  • Sunny Singh
    Sunny SinghJun 7, 2019

    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!

  • Joe Attardi
    Joe AttardiJun 7, 2019

    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.

  • William Moore
    William MooreJun 8, 2019

    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!

  • Max Tarsis
    Max TarsisJun 10, 2019

    it's just awesome
    thx a lot, man

Add comment