This is driving me crazy. I have no problem with select drop downs and text fields, but for some reason, I cannot get checkboxes working in a controlled fashion. That it is I want them to 'toggle' and listen to this event in a parent ponent.
I understand there is a 'checked' property for inputs of type checkbox. Selecting a checkbox gives it a value of 'on'. I take this 'on' value and convert it to true or false, and update the ponent accordingly.
For some reason, I cannot get this to work, either it is always selected, or it is never selected (if I switch the boolean switch).
export class ControlledCheckbox extends React.Component {
constructor(props) {
super(props);
this.state = {
select: false,
};
}
render() {
console.info("this.state.select - " + this.state.select);
let sel = false;
if (this.state.select !== "on") {
sel = true;
} else {
sel = false;
}
return (
<div>
<input
type="checkbox"
checked={sel}
onChange={this.handleChangeCheckbox}
/>
</div>
);
}
handleChangeCheckbox = (e) => {
console.info("here e.currentTarget.value " + e.currentTarget.value);
this.setState({
select: e.currentTarget.value,
});
//call passed through callback here
};
}
This is driving me crazy. I have no problem with select drop downs and text fields, but for some reason, I cannot get checkboxes working in a controlled fashion. That it is I want them to 'toggle' and listen to this event in a parent ponent.
I understand there is a 'checked' property for inputs of type checkbox. Selecting a checkbox gives it a value of 'on'. I take this 'on' value and convert it to true or false, and update the ponent accordingly.
For some reason, I cannot get this to work, either it is always selected, or it is never selected (if I switch the boolean switch).
export class ControlledCheckbox extends React.Component {
constructor(props) {
super(props);
this.state = {
select: false,
};
}
render() {
console.info("this.state.select - " + this.state.select);
let sel = false;
if (this.state.select !== "on") {
sel = true;
} else {
sel = false;
}
return (
<div>
<input
type="checkbox"
checked={sel}
onChange={this.handleChangeCheckbox}
/>
</div>
);
}
handleChangeCheckbox = (e) => {
console.info("here e.currentTarget.value " + e.currentTarget.value);
this.setState({
select: e.currentTarget.value,
});
//call passed through callback here
};
}
Share
Improve this question
edited May 2, 2020 at 13:07
Dennis Vash
54k12 gold badges117 silver badges132 bronze badges
asked May 2, 2020 at 12:52
Oliver WatkinsOliver Watkins
13.6k39 gold badges134 silver badges252 bronze badges
1
- codesandbox.io/s/objective-tereshkova-tcdq9?file=/src/App.js – acbay Commented May 2, 2020 at 13:06
2 Answers
Reset to default 5value
serves a different purpose for checkbox
inputs and you should not use it to define your state's value. You need to take a look at the e.currentTarget.checked
instead.
export class ControlledCheckbox extends React.Component {
constructor(props) {
super(props);
this.state = {
select: false,
}
}
handleChangeCheckbox = e => {
this.setState({
select: e.currentTarget.checked // <--
})
}
render() {
return (
<div>
<input type="checkbox"
checked={this.state.select}
onChange={this.handleChangeCheckbox} />
</div>
);
}
}
If you are working with multiple inputs (not only checkboxes) you can follow the approach suggested by react docs, where you can cover multiple input types with only one setState
. Keep in mind to define a name
in this case, so you can separate your inputs:
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<div>
<input type="checkbox"
name="hasValue"
checked={this.state.select}
onChange={this.handleChangeCheckbox} />
</div>
);
}
Your question is about controlled inputs, however your checkbox isn't controlled yet. You rely on the value stored inside checkbox, not inside the state.
this.setState({
select: e.currentTarget.value, // here
});
Use a value
that es from the state instead.
this.setState((prevState) => ({
select: !prevState.select,
}));
Note: You can remove the conditions from the render, they are redundant.