【问题标题】:React Checkbox Stays Checked Even After Component is Unmounted即使在卸载组件后,React 复选框仍然处于选中状态
【发布时间】:2017-09-14 20:11:24
【问题描述】:

所以,我有一个带有复选框的项目列表,就像经典的待办事项应用程序一样。

当我选择“Johnny”然后单击“删除选定的记录”时,Johnny 确实消失了。耶!

但是,一旦 Johnny 走了,Renee 就被检查了。

我没有点击 Renee。我只点击了 Johnny,但是一旦 Johnny 被删除,Renee 就会被选中。什么鬼?

显然,在复选框 DOM 保持选中状态的情况下发生了一些事情,即使我只是在其位置上清除了复选框。

我尝试通过更新 componentWillUnmount 中的状态来解决这个问题,但没有奏效。

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;

Person 组件中的其他所有内容都运行良好。删除任何记录后,如何取消选中所有复选框?

更新:这里是 PeopleList,包含所有人员的组件。

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;

【问题讨论】:

  • 能展示一下渲染personlist的组件代码吗?
  • @Chris 刚刚更新。

标签: javascript reactjs dom checkbox redux


【解决方案1】:

我认为您可能在状态和传递功能方面遇到了一些问题。我创建了一个示例,该示例使用简单的映射和过滤功能来反映您当前的实现,以模仿删除。如果我不得不猜测您可能没有跟踪检查和删除哪些数据,并且可能会缓存检查的值。正如您在下面的代码中看到的,您可以实施一些建议以使代码更简单:

  • 将 Person 保留为 Dumb/Leaf 组件,毕竟它只呈现 你的复选框,不要试图在那里保持选中状态。 (至少 删除通常不需要的卸载生命周期)
  • 您可以使用context 或者可以帮助您跟踪状态的库,mobx 实现起来相当简单。
  • 如果您不需要人员列表中的任何额外逻辑,onClick={() =&gt; this.props.deleteRecords()}&gt; 可能看起来像 onClick={this.props.deleteRecords.bind(this)}&gt; 这样更好。

看看这里并尝试运行它:

import React, {Component} from 'react';
import {render} from 'react-dom';

const Person  = ({person, setForDelete}) => (
          <div>
            <input type="checkbox" name="person" checked={person.checked} onChange={setForDelete.bind(this, person)} />
            {person.name}
          </div>
);


class PeopleList extends Component {

  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>
    );
  }

} // end class

class App extends React.Component {

  constructor(props) {
    super(props)
    this.state = {people:[{id:1, name:'Cesar', checked:false},{id:2, name:'Jose', checked:false},{id:3, name:'Marbel', checked:false}]}
  }

  deleteRecords() {
    const people = this.state.people.filter(p => !p.checked);

    this.setState({people});
 }

  setForDelete(person) {
    const checked = !person.checked;
    const people = this.state.people.map((p)=>{
      if(p.id === person.id)
        return {name:person.name, checked};
      return p;
    });

    this.setState({people});
  }

  render () {

    return <PeopleList people={this.state.people} deleteRecords={this.deleteRecords.bind(this)} setForDelete={this.setForDelete.bind(this)}/>;
  }
}

render(<App/>, document.getElementById('app'));

【讨论】:

    【解决方案2】:

    尝试更改 PeopleList 中的以下行

    {this.props.people.map((person, i) => {
          return <Person key={person._id} person={person} setForDelete={this.props.setForDelete} />;
        })}
    

    【讨论】:

      【解决方案3】:

      不要使用数组索引作为关键属性!

      键是 React 用来识别 DOM 元素的唯一道具。如果键与以前相同,则在您的情况下 0 React 假定 DOM 元素表示与以前相同的内容 - 即使现在还有另一个文本。

      所以 React 将重新呈现状态并更新选中的属性。

      使用独特的东西,例如:

      <Person key={person + '_' + i} ...
      

      【讨论】:

        猜你喜欢
        • 2023-01-14
        • 2017-01-16
        • 2020-08-12
        • 1970-01-01
        • 1970-01-01
        • 2019-07-13
        • 2021-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多