1.遇到的八阿哥:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
2.招来八阿哥的骚操作:
componentDidMount() {
window.addEventListener('resize', this.reComputeHeight.bind(this));
}
reComputeHeight = () => {
this.setState({
tableHeight: document.body.clientHeight - 450,
});
}
在componentDidMount生命周期中监听了resize,监听函数调用了setState,setState必须在组件确定渲染完成的情况下调用,而监听函数虽然在componentDidMount中声明,而监听的回调却可能发生在其他生命周期时。
//所以要做的第一步补救就是,当组件被卸载时,销毁对resize的监听
componentWillUnmount() {
window.removeEventListener('resize', this.reComputeHeight.bind(this));
}
这么做是可以解决一部分人的问题了,但是如果你不止一个组件做了监听,那么在两个都加了监听的组件间切换还是会报错。(这里其实我不是很理解,按道理讲一个组件在卸载时将监听都移除了,新组件被渲染时重新添加监听,互不影响,推测组件1的componentWillUnmount还未执行完,组件2的componentDidMount就已经执行了?不是串行的咩???)
不管怎样机智的我还是找到了干掉报错的方法
//当执行setState前检查下是否已经可以取到一个DOM,如果可以则证明组件渲染完成了
/*
取DOM的方法,react提供了三种。
1. 第一个字符串方法,简单但是被废弃了
2. 第二个回调方法,看着就麻烦不想用
3. 第三个createRef方法,简单但是要react@16.3版本才支持
*/
//坑爹的事出现了,我们项目目前是依赖react@15.6,我会为了解决一个报错而去做升级版本库的蠢事???...我做了==
/*
升级的react相关库:
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
*/
//其实还有几个相关库没升级,升级会导致新的报错,心累了,拖鞋...
//升级完终于可以用我喜欢的方法了!完全版代码!
componentDidMount() {
//组件渲染完成,添加监听
window.addEventListener('resize', this.reComputeHeight.bind(this));
}
componentWillUnmount() {
//组件卸载,移除监听
window.removeEventListener('resize', this.reComputeHeight.bind(this));
}
//获取DOM
myRef = React.createRef();
reComputeHeight = () => {
if (this.myRef.current) {//若DOM存在,执行setState
this.setState({
tableHeight: document.body.clientHeight - 450,
});
}
}
<div ref={this.myRef} >我是一个随便的DOM,能娶到我说明你的组件渲染成功了</div>