即使在卸载组件后,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=() => this.props.deleteRecords()>
可能看起来像 onClick=this.props.deleteRecords.bind(this)>
这样更好。
看看这里并尝试运行它:
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 复选框仍然处于选中状态的主要内容,如果未能解决你的问题,请参考以下文章
React-router:一旦安装,永远不要卸载路由上的组件,即使路由更改
ag-grid React Header组件选择所有复选框选项无法在移动设备和平板电脑上正常工作