reactjs - 卸载子组件抛出无法在 reactjs 中的卸载组件上调用 setstate
问题描述
当我卸载子组件时,我得到无法设置未安装组件警告的状态。
我想做什么?我有一个父组件 ViewItems 和子组件 ItemsList。在 ViewItems 组件中,我使用 load_items 方法从服务器检索项目列表,该方法又使用 client.get_file 方法。并将这些项目列表存储在名为“项目”的状态中。我在 componenDidMount 方法中调用了这个 load_items 方法。但是,这不会显示另一个项目的新详细信息。
给问题一个清晰的画面。考虑我在一页中呈现项目。当我单击一个项目时,它会将我带到另一个页面(在本例中为已安装的项目组件),当我单击按钮单击以查看项目详细信息时,它会列出与该项目相关的详细信息。当我单击按钮返回项目列表(我们之前所在的页面)并单击另一个项目时。它应该显示与单击的新项目相关的详细信息。
但是,在这种情况下,当我单击新项目时,它会显示以前的项目详细信息,除非页面刷新。
为了克服这个问题,在 componentDidUpdate 上我调用了这个 load_items 方法。这行得通。但是,当我不关闭子组件时,这意味着显示项目详细信息的布局......我收到无法调用 setstate on unmounted component 警告。卸载子组件后会显示此错误。
下面是代码,
class ViewItems extends React.PureComponent {
constructor(props) {
super(props);
this.default_root_item = {
name: 'Items',
index: 0,
children: [],
};
this.state = {
root_items: this.default_root_item,
items: [],
};
}
componentDidMount() {
this.load_items();
}
componentDidUpdate() {
this.load_items();
}
componentWillUnmount() {
this.unlisten_path_change();
}
load_items = () => {
const file_name = 'file_name.json';
client.get_file(this.props.item_id, file_name, 'json')
.then((request) => {
const items = request.response;
this.setState({items: [this.default_root_item]});}
this.handle_path_change(this.props.location.pathname);})};
return (
<ChildComponent
on_close={this.handle_item_close}
root_item={this.state.root_item}/>)}
export default class ChildComponent extends React.PureComponent {
<Items
items={root_item}/>
function Items(props) {
return (
<ul className="Items_list">
<div className="items">
{props.items.map((item, index) => {
return (
<Item
key={index}
item={item}
/>
);
})}
</div>
</ul>
);}
}
解决方案
首先,不要在没有检查 props 是否更改的情况下在 componentDidUpdate 中进行 API 调用。
第二:从 API 请求响应设置状态时,检查组件是否仍然挂载
class ViewItems extends React.PureComponent {
constructor(props) {
super(props);
this.default_root_item = {
name: 'Items',
index: 0,
children: [],
};
this.state = {
root_items: this.default_root_item,
items: [],
};
this._isMounted = true;
}
componentDidMount() {
this.load_items();
}
componentDidUpdate(prevProps) {
if (prevProps.item_id !== this.props.item_id) {
this.load_items();
}
}
componentWillUnmount() {
this._isMounted = false;
this.unlisten_path_change();
}
load_items = () => {
const file_name = 'file_name.json';
client.get_file(this.props.item_id, file_name, 'json')
.then((request) => {
const items = request.response;
if (this._isMounted) {
this.setState({items: [this.default_root_item]});
this.handle_path_change(this.props.location.pathname);
}
})
};
推荐阅读
- c - 我对 C 编码很陌生,我不知道为什么我的粗略计算器代码不起作用
- asp.net - ASP.NET Core:URL 重写
- socket.io - 如何避免使用 socket.io 制作单体应用
- multiple-columns - 列填充平衡在 Chrome 和 Microsot 边缘中不起作用
- rust - 将值从向量移动到预定义切片的惯用方式?
- python - 如何根据特定的颜色轮廓或边框找到轮廓?
- typescript - 无法使用打字稿启动博览会裸工作流程
- python - Django 模型 FileField 大文件上传
- html - Handel 从 iframe 中另存为
- linux - 为 pdftohtml 选择编码