Sandhya
Sandhya

Reputation: 541

How to set the handler for multiple checkboxes in react?

I've created multiple checkboxes in my small project. I'm facing a problem in retrieving the info of the checkbox while giving a checkmark. if I give a checkmark on toys then the value should be toys or if I give checkmark on both toys and lights i should get both toys and lights in the console.

Here is code:

import React from "react";
import { render } from "react-dom";
import { Segment, Form, Checkbox, Button } from "semantic-ui-react";
import axios from "axios";
export default class ShowForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      event: ""
    };
  }
  handleCheck = event => {
    console.log("Hello", event);
  };
  render() {
    return (
      <div>
        <Segment>
          <Form>
            <Checkbox label="Cake" onChange={this.handleCheck} />
            <br />
            <Checkbox label="Lights" onChange={this.handleCheck} />
            <br />
            <Checkbox label="Flowers" onChange={this.handleCheck} />
            <br />
            <Checkbox label="Toys" onChange={this.handleCheck} />
            <br />
            <Button onClick={this.handleSubmit}> Submit </Button>
          </Form>
        </Segment>
      </div>
    );
  }
}

Here is whole code: "https://codesandbox.io/s/zealous-paper-p9zb5"

Can anyone please help me in this issue?

Upvotes: 0

Views: 2259

Answers (2)

keikai
keikai

Reputation: 15146

You need an array to store all the checked status.

handleCheck = id => () => {                      // Get indentify from each element
  const { checkedList } = this.state;
  const result = checkedList.includes(id)        // Check if checked at this moment
    ? checkedList.filter(x => x !== id)          // If checked, remove
    : [...checkedList, id];                      // If not, add
  this.setState({ checkedList: result }, () => { // setState
    console.log(this.state.checkedList);         // setState is async, log in callback
  });
};

And if you want, you can make the Checkbox component a common one so you don't need to bind the label in three places in each of it.

<Checkbox
  label="Cake"
  onChange={this.handleCheck("Cake")}
  checked={checkedList.includes("Cake")}   // If included, checked
/>

Another minimum reproducible demo

Try it in-text:

const list = [...Array(10).keys()].map(x => ({ id: x }));
const App = () => {
  const [selected, setSelected] = React.useState([]);
  const onChangeHandler = id => () => {
    selected.includes(id)
      ? setSelected(selected.filter(x => x !== id))
      : setSelected([...selected, id]);
  };
  const onRemove = () => {
    setSelected([]);
  };
  return (
    <div className="App">
      {list.map(item => (
        <input
          type="checkbox"
          key={item.id}
          checked={selected.includes(item.id)}
          onChange={onChangeHandler(item.id)}
        />
      ))}
      <br />
      <button onClick={onRemove}>Remove all</button>
      <div>{selected.join(",")}</div>
    </div>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

Upvotes: 3

Rusty
Rusty

Reputation: 4473

Pretty sure, you can ES6 named properties and arrow functions to create a clean flow

Consider a state:

this.state={
   isToy: false,
   isCake: false,
   isFlower: false,
   isLight: false
}

Add a property of Name. These names should ideally match the ones in state.

<Form>
    <Checkbox name="isCake" label="Cake" checked={this.state.isCake} onChange={this.handleCheck} />
    <Checkbox name="isLight" label="Lights" checked={this.state.isLight} onChange={this.handleCheck} />
    <Checkbox name="isFlower" label="Flowers" checked={this.state.isFlower} onChange={this.handleCheck} />
    <Checkbox name="isToy" label="Toys" checked={this.state.isToy} onChange={this.handleCheck}  />
    <Button onClick={this.handleSubmit}> Submit </Button>
</Form>

Then write the handleCheck arrow function, using ES6 name properties feature to access state property:

handleCheck = (event) => {
   let name = event.target.name
   this.setState{[name]: !this.state[name]}
}

References:

React Controlled Forms: https://reactjs.org/docs/forms.html

Semantic UI Checkboxes: https://react.semantic-ui.com/modules/checkbox/#usage-remote-control

Upvotes: 0

Related Questions