【发布时间】:2019-10-10 19:02:42
【问题描述】:
从另一个类组件打开对话框时出现错误:“无法对未安装的组件执行 React 状态更新。这是一个无操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消componentWillUnmount 方法中的所有订阅和异步任务”
index.js
import ...
class AdMenu extends Component {
componentWillMount = () => {
this.onSearch();
};
onOpenInsert = () => {
showDetailDialog();
};
onSearch = () => {
fetch(_url, ...)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw response;
}
})
.then(responseJson => {
this.setState({...});
})
.catch(response => {...});
};
render() {
return (
<div>
<DetailDialog />
<Button color="primary" onClick={this.onOpenInsert}>Add New</Button>
<BootstrapTable .... />
</div>
);
}
}
export default withTranslation()(AdMenu);
DetailDialog.js
export var showDetailDialog = function () {
this.setState({open: true});
console.log('Mounted: ' + this.mounted);
};
class DetailDialog extends React.Component {
mounted = false;
controller = new AbortController();
constructor(props) {
super(props);
this.state = {open: false};
showDetailDialog = showDetailDialog.bind(this);
}
componentDidMount() {
console.log('componentDidMount');
this.mounted = true;
}
componentWillUnmount(){
console.log('componentWillUnmount');
this.mounted = false;
}
onClose = () => {
this.setState({open: false});
};
render() {
return (
<Modal isOpen={this.state.open} toggle={this.onClose} className={"modal-primary"} >
<ModalHeader toggle={this.onClose}>Detail</ModalHeader>
<ModalBody>
...
</ModalBody>
</Modal>
);
}
}
export default withTranslation()(DetailDialog);
我有一个 DetailDialog 导出类组件和函数 showDetailDialog。它已导入 index.js 页面。
当我第一次打开页面并单击打开对话框时,工作正常。但是当我在菜单中通过路由器切换到另一个页面然后第二次再次打开页面时,控制台日志中出现错误。
我尝试使用 this.mounted var 检查卸载的组件,但我不知道如何设置状态以在组件第二次和下一次卸载时打开详细对话框。
我尝试使用 controller = new AbortController();和 componentWillUnmount() 中的 controller.abort() 但不起作用。
或者有解决这个问题的办法吗?
谢谢!
CodeSandbox 上的来源:https://codesandbox.io/s/coreuicoreuifreereactadmintemplate-5unwj
步骤测试:
点击广告菜单(第一次)
点击广告组
点击广告菜单(第 2 次)
点击广告菜单中的打开对话框
查看控制台日志浏览器
文件:src/views/category
节点 v11.12.0
Npm 6.7.0
窗口 10
【问题讨论】:
-
使用
componentDidMount()而不是componentWillMount()并检查问题是否仍然存在。顺便说一句,请始终避免componentWillMount()。 -
另外,相关:stackoverflow.com/a/53949849/482868 我认为,您应该将您的
this.setState()包装到ifs 中,以检查组件是否仍然安装。有意义吗? -
感谢 Igor Soloydenko!,我尝试了 componentWillMount() { this.mounted = true;但仍然错误,因为当 didMount 时没有再次安装某些东西,或者当 willUnmount 时某些东西没有取消。我不知道那是什么:|
-
我也试过 if (this.mounted) { this.setState({ open: true }); }else{//怎么办?}。它没有错误,也没有显示对话框
-
@IgorSoloydenko:或者是否有另一种方法可以从 index.js 打开详细对话框而不导出函数 showDetailDialog ?
标签: reactjs opendialog