0

How would I pass an array into a setState? As you can see there is a checkbox that renders and once onchange is called the id is put into the state but if there are multiple checkboxes it overwrites each time onchange is called.

  getInitialState() {
    return {
        listid: []
    }
},    


  handleChange() {
    this.setState({
        listid: e.target.name,
    });
},

 renderCheckbox() {
    const data = this.state.data || [];
    return data.map((list, i) => {
        return (
            <Checkbox
                key={i}
                onChange={this.handleChange}
                name={list.id}
                value="Yes"
                label={description}
            />
        );
    });
},
2
  • So you want to keep an array of listid indicating if the checkbox is checked or not? Commented Aug 7, 2018 at 12:27
  • Yes that is precisely what i want it to do Commented Aug 7, 2018 at 12:31

3 Answers 3

1

You could check in your handleChange function if the checkbox id is present in the listid array. If it is, you remove it. If it isn't, you add it.

You can then check if the checkbox id is present in the listid array in the render method to decide if it should be checked or not.

Example

class App extends React.Component {
  state = {
    checkboxes: [{ id: "1" }, { id: "2" }, { id: "3" }, { id: "4" }],
    listIds: []
  };

  handleChange = event => {
    const { name } = event.target;
    this.setState(prevState => {
      const { listIds } = prevState;
      if (listIds.includes(name)) {
        return { listIds: listIds.filter(id => id !== name) };
      } else {
        return { listIds: [...listIds, name] };
      }
    });
  };

  render() {
    const { checkboxes, listIds } = this.state;
    return (
      <div>
        {checkboxes.map(checkbox => (
          <input
            key={checkbox.id}
            type="checkbox"
            checked={listIds.includes(checkbox.id)}
            name={checkbox.id}
            onChange={this.handleChange}
          />
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

Sign up to request clarification or add additional context in comments.

2 Comments

I was going to write a very similar code to this, as always you are fast :) But, I am happy that I can reach the very similar conclusions like those situations. I feel that I'm getting better everyday.
I get Uncaught Error: mergeIntoWithNoDuplicateKeys():Tried to merge two objects with the same key: errors
0

Since it is an array containing the state of multiple checkboxes, you need to tell handleChange which checkbox you want to change:

<Checkbox
  key={i}
  onChange={(e) => this.handleChange(e, i)}
  name={list.id}
  value="Yes"
  label={description}
/>

You must then create a temporary copy of the state array, mutate the appropriate item, then replace the old array with the new one:

handleChange(e, i) {
  const arr = this.state.listid.slice();
  arr[i] = e.target.name;
  this.setState({listid: arr});
}

A better approach though would be to pass the index i as a prop down to Checkbox and then do: this.props.onClick(this.props.index) or similar.

Comments

0

Ah, classic. Here are the changes you can make to renderCheckBox.

        <Checkbox
            key={i}
            onChange={(el) => this.handleChange(el, i)}
            name={list.id}
            value="Yes"
            label={description}
        />

In your handleChange, you can then do

handleChange(el, index) {
  let listid = [ ...this.state.listid ];
  listid[index] = el.target.name;
  this.setState({
    listid,
});

2 Comments

Hi there. Mutating the state is not so advisable. Maybe instead of assigning it directly you can use const listid = [ ...this.state.listid ];
I get Uncaught Error: mergeIntoWithNoDuplicateKeys():Tried to merge two objects with the same key: errors

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.