Pass parameters to React event handler without wrapping the function

MilkJar
2 min readJun 20, 2020

--

Its common to need to pass arguments to a React event handler (such as onClick or onChange) when a button is clicked or radio input changed.

In the following code we pass the rate function to the onClick property, the problem is that we also want to pass the selected rating to the handler

const rate = (val) => {
// Send rating
}
return (<button onClick={rate}>Rate 1</button>);

There are many ways of achieving this.

We could wrap function in another anonymous function, giving us control over the arguments that are passed.

const rate = (val) => {
// Send rating
}
return (<button onClick={() => rate(1)}>Rate 1</button>);

Or maybe bind the required value to create a new function that has the argument(s) bound.

const rate = (val) => {
// Send rating
}
return (<button onClick={rate.bind(null, 1)}>Rate 1</button>);

We could also create a factory function that will return a new function that calls rate with the correct value.

const rate = (val) => {
// Send rating
}
const rateFactory = (val) => () => rate(val);return (<button onClick={rateFactory(1)}>Rate 1</button>);

The problem with the above options is that we are creating new functions each time. This is probably fine with one or two elements, but if we are attaching click events to a large number of elements we need a better solution.

We can take advantage of data-* attributes as medium for passing the data to the handler function. They can be accessed via the React event argument passed to the function.

const rate = () => {
const { value, category } = event.target.dataset;
// Send rating
}
return (<button data-value={1} data-category={'sandwich'} onClick={rate}>Rate 1</button>);

Caveat

Values assign to dataset are always serialized to strings, so to pass a JSON blob you would have to `JSON.stringify()` the value. Likewise with numbers, in the handler function you will need to convert the string to a number.

Bonus

data-* attributes can be accessed by your css

--

--