即使在卸载组件后,React 复选框仍然处于选中状态

Posted

技术标签:

【中文标题】即使在卸载组件后,React 复选框仍然处于选中状态【英文标题】:React Checkbox Stays Checked Even After Component is Unmounted 【发布时间】: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 刚刚更新。 【参考方案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 ...

【讨论】:

以上是关于即使在卸载组件后,React 复选框仍然处于选中状态的主要内容,如果未能解决你的问题,请参考以下文章

Codeigniter:选中复选框时表单验证仍然失败

React-router:一旦安装,永远不要卸载路由上的组件,即使路由更改

ag-grid React Header组件选择所有复选框选项无法在移动设备和平板电脑上正常工作

即使卸载后旧的 GCM 令牌仍然存在吗?

React Update Fetch on Checkbox Click

即使设置为 false,使用条件渲染的 React Native 仍然尝试访问状态