My onchange function on my checkbox is always undefined. I made a sandbox to simplify my issue. I've tried changing it back and forth between an arrow and a regular function, and leaving the binding as its default state vs tying it to its binding in the constructor.
import "./styles.css";
import React, { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.renderCheckboxes = this.renderCheckboxes.bind(this);
this.checkboxChange = this.checkboxChange.bind(this);
}
checkboxChange = (event) => {
console.log("CHANGED");
}
renderCheckboxes(checkboxes) {
return checkboxes.map(function (obj, idx) {
return (
<div>
<label>{obj.name}</label>
<input type="checkbox" onChange={this.checkboxChange} />
</div>
);
});
}
render() {
const cbList = [
{ name: "A", mood: "Happy" },
{ name: "B", mood: "Sad" },
{ name: "C", mood: "Mad" }
];
return <>{this.renderCheckboxes(cbList)}</>;
}
}
export default App;
CodePudding user response:
Your function is undefined because you are losing your context when your checkboxes.map
happens.
renderCheckboxes(checkboxes) {
return checkboxes.map(function (obj, idx) { // here
return (
<div>
<label>{obj.name}</label>
<input type="checkbox" onChange={this.checkboxChange} />
</div>
);
});
}
You can change the function for an arrow function, so you won't lose context:
renderCheckboxes(checkboxes) {
return checkboxes.map((obj, idx) => { // here
return (
<div>
<label>{obj.name}</label>
<input type="checkbox" onChange={this.checkboxChange} />
</div>
);
});
}
It might not be the case, but if you need to send some parameter on your checkboxChange
call, you could use it like this:
checkboxChange = (value) => { // need to set the variable here
console.log(value);
}
renderCheckboxes(checkboxes) {
return checkboxes.map((obj, idx) => {
return (
<div>
<label>{obj.name}</label>
<input type="checkbox" onChange={() => this.checkboxChange('test')} /> <!-- so you can pass it from here -->
</div>
);
});
}
CodePudding user response:
Easy fix, it's because the binding doesn't work within the map
function like you have now. To see this in action, try just rendering one checkbox, without map
and you'll see your checkbox change method work.
Two changes I suggest:
- Change map method to an arrow function:
return checkboxes.map((obj, idx) => {
...
}
- Change onChange to an arrow function:
onChange={() => this.checkboxChange()}