Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Checkbox Stays Checked Even After Component is Unmounted

So, I have a list of items with checkboxes, just like a classic todo application.

enter image description here

When I select "Johnny" and then click, "Delete Selected Records," Johnny does go away. Yay!

enter image description here

But, once Johnny is gone Renee is checked, now.

enter image description here

I did NOT click on Renee. I only clicked on Johnny, but once Johnny was deleted Renee became checked. wtf?

Obviously, something is happening where the checkbox DOM is staying true of checked, even though I just wiped out the checkbox in its place.

I tried solving this through updating the state in componentWillUnmount, but that didn't work.

import React, {Component} from 'react';

class Person extends Component {

  constructor(props) {
    super(props);

    this.state = {
      checked: false
    }

    this.checkboxToggle = this.checkboxToggle.bind(this);
  }

  checkboxToggle() {
    this.setState({ checked: !this.state.checked }, () => {
      if (this.state.checked === false) {
        console.log("Checked should be FALSE");
      }
      else if (this.state.checked === true) {
        console.log("Checked should be TRUE");
        this.props.setForDelete(this.props.person._id);
      }
    });
  }

  componentWillUnmount() {
    this.setState({ checked: false });
  }

    render() {
        return (
          <div>
            <input type="checkbox" name="person" checked={this.state.checked} onChange={this.checkboxToggle} />
            {this.props.person.name} ({this.props.person.age})
          </div>
        );
    }
}

export default Person;

Everything else in the Person component is working fine. How do I get all the checkboxes to become unchecked once I have deleted any of the records?

UPDATE: Here's PeopleList, the component that holds all of the Persons.

import React, { Component } from 'react';
import Person from './Person';

class PeopleList extends Component {

  constructor(props) {
    super(props);
  }

  componentWillUnmount() {
    this.props.resetSetForDeleteArr();
  }

  render() {
    return(
      <div>
        {this.props.people.map((person, i) => {
          return <Person key={i} person={person} setForDelete={this.props.setForDelete} />;
        })}
        <div onClick={() => this.props.deleteRecords()}>Delete Selected Records</div>
        <div onClick={() => this.props.resetSetForDeleteArr()}>Empty Array.</div>
      </div>
    );
  }

} // end class

export default PeopleList;
like image 745
Gabriel Kunkel Avatar asked Apr 18 '17 20:04

Gabriel Kunkel


2 Answers

Don't use an array index as key attribute!

A key is the only prop React uses to identify DOM elements. If the key is the same as before, in your case 0 React assumes that the DOM element represents the same content as before - even if there's another text now.

So React would NOT rerender the state and update the checked property.

Use something unique instead like:

<Person key={person + '_' + i} ...
like image 71
Chris Avatar answered Oct 20 '22 00:10

Chris


Try changing the below line in your PeopleList

{this.props.people.map((person, i) => {
      return <Person key={person._id} person={person} setForDelete={this.props.setForDelete} />;
    })}
like image 35
Panther Avatar answered Oct 20 '22 00:10

Panther