Hello how can I handle onChange for multiple check box? The following example allows me to control the value of one checkbox.
class App extends Component {
constructor() {
super();
this.state = {
i_agree: false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({i_agree: !this.state.i_agree});
}
handleSubmit(event) {
console.log(this.state);
event.preventDefault();
}
render() {
return (
<div>
<h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
<form onSubmit={this.handleSubmit}>
<label>
<input
type="checkbox"
defaultChecked={this.state.i_agree}
onChange={this.handleChange}
/> I Agree with this content...
</label>
<label>
<input
type="checkbox"
defaultChecked={this.state.isChecked}
onChange={this.handleChange}
/> I want to control this...
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
How can I set my handleChange function to handle changes for each checkbox instead of checking for one.
Attempt 1
class App extends Component {
constructor() {
super();
this.state = {
i_agree: false,
isChecked: false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
[e.target.name]: !e.target.value
});
}
handleSubmit(event) {
console.log(this.state);
event.preventDefault();
}
render() {
return (
<div>
<h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
<form onSubmit={this.handleSubmit}>
<label>
<input
type="checkbox"
defaultChecked={this.state.i_agree}
onChange={this.handleChange}
name="i_agree"
/> I Agree with this content...
</label>
<label>
<input
type="checkbox"
defaultChecked={this.state.isChecked}
onChange={this.handleChange}
name="isChecked"
/> I want to control this...
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
I Updated the onChange handler and added name attributes in each label. But this did not work or threw any errors.
I would use checked
instead of defaultChecked
to have a controlled checkbox input.
for handleChange
you can use name
and checked
attributes to update checkbox state (you could also do a flip on its boolean state instead of using checked
). this way you can have only one handler for all your checkboxes.
Typescript solution
import React from "react";
interface CheckboxProps {
checked: boolean;
label: string;
name: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
// I abstracted Checkbox to a component but it's up to you
const Checkbox = ({ checked, onChange, label, name }: CheckboxProps) => (
<label>
<input
type="checkbox"
checked={checked} // use checked to have a controlled component
onChange={onChange}
name={name}
/>
{label}
</label>
);
interface AppState {
iAgree: boolean;
wantCookies: boolean;
wishList: boolean;
}
class App extends React.Component<{}, AppState> {
// constructor method is called implicit you can define state outside
// for binding methods, you can declare them as arrow functions
state = {
iAgree: false,
wantCookies: false,
wishList: false
};
// extract name and checked properties
handleChange = ({
target: { name, checked }
}: React.ChangeEvent<HTMLInputElement>) =>
this.setState({ [name]: checked } as Pick<AppState, keyof AppState>);
handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
console.log(this.state);
event.preventDefault();
};
render() {
const { iAgree, wantCookies, wishList } = this.state;
return (
<div>
<h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
<form onSubmit={this.handleSubmit}>
<Checkbox
onChange={this.handleChange}
name={"iAgree"}
checked={iAgree}
label={"I agree with terms"}
/>
<Checkbox
onChange={this.handleChange}
name={"wantCookies"}
checked={wantCookies}
label={"I want more cookies"}
/>
<Checkbox
onChange={this.handleChange}
name={"wishList"}
checked={wishList}
label={"Put Me on wishlist"}
/>
<br />
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
export default App;
Javascript solution
import React from "react";
// I abstracted Checkbox to a component but it's up to you
const Checkbox = ({ checked, onChange, label, name }) => (
<label>
<input
type="checkbox"
checked={checked} // use checked to have a controlled component
onChange={onChange}
name={name}
/> { label }
</label>
)
class App extends React.Component {
// constructor method is called implicit you can define state outside
// for binding methods, you can declare them as arrow functions
state = {
iAgree: false,
wantCookies: false,
wishList: false,
};
// extract name and checked properties
handleChange = ({target: { name, checked }}) => this.setState({[name]: checked});
handleSubmit= (event) => {
console.log(this.state);
event.preventDefault();
}
render() {
const { iAgree, wantCookies, wishList } = this.state
return (
<div>
<h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
<form onSubmit={this.handleSubmit}>
<Checkbox onChange={this.handleChange} name={'iAgree'} checked={iAgree} label={'I agree with terms'} />
<Checkbox onChange={this.handleChange} name={'wantCookies'} checked={wantCookies} label={'I want more cookies'} />
<Checkbox onChange={this.handleChange} name={'wishList'} checked={wishList} label={'Put Me on wishlist'} />
<br/>
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
export default App
fwiw I removed the constructor since it's not necessary. You can keep it though, it's only a cleaner way to declare your classes.
sandbox with implementation TS: https://codesandbox.io/s/so-multi-checkboxes-ts-qz20m
sandbox with implementation JS: https://stackblitz.com/edit/so-multi-checkboxes?file=src/App.js