I try to trigger an onClick event in a map function, and I get this error :
TypeError: Cannot read property 'handleClick' of undefined
How do we trigger an onClick event in a map function ?
Here is my code :
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
isToggleOn: true,
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
}));
}
render() {
if (this.props.data) {
var recipes = this.props.data.map(function (recipe, i) {
return (
<div
key={i}
className="col-8 offset-col-1 f-l relative m-t-10"
>
<div className="col-6 f-l">
<p className="col-8 f-l">{recipe.title}</p>
<button className="f-l" onClick={this.handleClick}>
Voir la recette
</button>
</div>
</div>
);
});
}
return (
<div className="RecipeList">
<div className="col-12">
{recipes}
<div className="both"></div>
</div>
</div>
);
}
}
Use an arrow function as the function given to map
instead and this
will be what you expect:
if (this.props.data) {
var recipes = this.props.data.map((recipe, i) => {
return <div key={i} className="col-8 offset-col-1 f-l relative m-t-10">
<div className="col-6 f-l">
<p className="col-8 f-l">{recipe.title}</p>
<button className="f-l" onClick={this.handleClick}>Voir la recette</button>
</div>
</div>;
});
}
Why this is the case is explained in detail here. Arrow functions don't provide their own this
binding, but instead retains the this
value of the enclosing lexical context.
This is how I would tackle a similar situation.
import React from "react";
import ReactDOM from "react-dom";
const stuff = ["one", "two", "three"];
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isToggleOn: true
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(val) {
console.log(val);
}
getStuff() {
var elements = stuff.map((value, key) => {
return (
<li key={key} onClick={() => this.handleClick(value)}>
{value}
</li>
);
});
return elements;
}
render() {
return <ul>{this.getStuff()}</ul>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
here is the sandbox -> https://codesandbox.io/embed/1rqw081oj7
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With