Reputation: 1871
I want to listen for click events on an arbitrary number of elements and inside the click event handler, I want to retrieve some info about the clicked element (info which was easily accessible during element creation).
A common solution to this problem is this:
render() {
return (
<div>
{this.props.users.map(user => (
<button onClick={() => this.buttonClicked(user.email)}>
{user.name}
</button>
))}
</div>
);
}
The flaw I see in this approach is that we're creating a new function for every element. Is that a problem worth solving? If it is, how do you feel about this solution:
render() {
return (
<div>
{this.props.users.map((user, index) => (
<button data-index={index} onClick={this.buttonClicked}>
{user.name}
</button>
))}
</div>
);
}
buttonClicked(event) {
const { index } = event.currentTarget.dataset;
const { email } = this.props.users[index];
// ...
}
Upvotes: 2
Views: 61
Reputation: 18113
Create another component and dispatch the event from it.
class Button extends React.PureComponent{
handleOnClick = ()=>{
const {onClick, ...rest} = this.props
if(onClick typeof ==='function'){
onClick(rest)
}
}
render(){
const {name} = this.props
return (
<button onClick={this.handleOnClick}>
{name}
</button>)
}
}
...
render() {
return (
<div>
{this.props.users.map(user => (
<Button {...user} key={user.email} onClick={this.buttonClicked} />
))}
</div>
);
}
Upvotes: 1
Reputation: 2638
I believe it is better to use a defined function instead of anonymous/inline functions, otherwise the onClick
handler only gets created during the render stage.
In your second example, you can actually bind the argument to the handler:
render() {
return (
<div>
{this.props.users.map((user, index) => (
<button data-index={index} onClick={this.buttonClicked.bind(this, user.email)}>
{user.name}
</button>
))}
</div>
);
}
Secondly, wanted to point out that there is no performance issue with having many handlers. React uses one event handler at the root of your document.
Upvotes: 0