1

I am fetching items from an api and then displaying them to user with checkboxes. When user clicks on an item the item's value should be added to user's items array. Also by unchecking it, it should be removed from the array...

I know the logic behind checkboxes and state and arrays, however I simply cannot understand what is going wrong here in my code. My code indeed adds items to user's array but when I try to uncheck the item all of the items except the clicked item are removed...

class StepThree extends Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedItems: []
        };
    };

    handleCheckbox = e => {
        let { selectedItems } = this.state;
        const item = e.target.name;
        if (selectedItems.includes(item)) {
            const index = selectedItems.indexOf(item);
            this.setState({ selectedItems: selectedItems.splice(index, 1)});
        } else {
            selectedItems = selectedItems.concat(item);
            this.setState({ selectedItems: selectedItems });
        }
    };

    render() {
        const { categories } = this.props;
        const { selectedItems } = this.state;

        return (
            <Content>
                {categories.map(item => (
                    <label key={item.name}>
                        {item.name}
                        <Checkbox
                            name={item.name}
                            checked={selectedItems.includes(item.name)}
                            onChange={this.handleCheckbox}
                            />
                    </label>
                ))}
            </Content>
        );
    }
}

note: sorry for a very bad example of the code, I am still kind of new in react. However if you have any other tips, please advise.

1
  • .splice() will return the removed items from the array. Try this: if (selectedItems.includes(item)) { const index = selectedItems.indexOf(item); selectedItems.splice(index, 1) this.setState({ selectedItems }); } Commented Sep 3, 2019 at 19:01

2 Answers 2

1

.splice() will return the removed items from the array.

It will work if you call it, and then set selectedItems state:

if (selectedItems.includes(item)) { 
  const index = selectedItems.indexOf(item); 
  selectedItems.splice(index, 1); 
  this.setState({ selectedItems }); 
}
2
  • Works! Thanks a lot. I am however interested if this is even a good practice since checkboxes for items are so common among the web and surprisingly haven't found the same type of logic I used... Commented Sep 3, 2019 at 19:19
  • I personally like having one state value (boolean) for each checkbox. Each checkbox is essentially an on/off switch. Your way introduces some functional programming which is neat, but I also think there is much more room for error or unwanted behaviors that way. Commented Sep 3, 2019 at 19:26
0

array.splice() removes the selected item from the underlying array and returns an array of the deleted items. To fix this you can just change this.setState({ selectedItems: selectedItems.splice(index, 1)}); to this.setState({ selectedItems: selectedItems.filter(selectedItem => selectedItem === item)});

1
  • this doesn't seem to be working for me. The problem is the same: I can check items and it adds them to user's array, however when I uncheck them all items except the one I clicked before function was called are removed and only one remains in the array. Commented Sep 3, 2019 at 19:17

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.