当我执行以下代码时(请参阅下面的代码段),我收到警告:
警告:setState(...):只能更新已安装或安装的组件。这通常意味着您在已卸载的组件上调用了setState()。这是一个无操作。请检查Blinker组件的代码。
我的Mounter类下的componentWillUnmount()方法中是否存在错误?谢谢!
class Blinker extends React.Component {
constructor(props) {
super();
this.state = {
appear: true
}
this.blinker = this.blinker.bind(this);
}
blinker() {
this.setState({appear: !this.state.appear });
}
componentDidMount() {
setInterval(this.blinker, 300)
}
render() {
return (
<div>
{ (this.state.appear) && "xxx" }
</div>
);
}
}
class Mounter extends React.Component {
constructor(props) {
super();
this.state = {
render: true
};
this.interval = null;
}
componentDidMount() {
this.interval = setTimeout( () =>
this.rendering(), 1500
);
}
componentWillUnmount() {
clearInterval(this.interval);
}
rendering() {
this.setState({ render: !this.state.render });
}
render() {
return (
<div>
<h1>
{ this.state.render && <Blinker /> }
</h1>
</div>
);
}
}
ReactDOM.render(<Mounter />, app);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
答案 0 :(得分:1)
定时器方法可能很棘手,因为它们可能在componentWillUnmount
触发之前触发,但状态设置可能在组件卸载后发生,因为setState
是异步的。要处理此问题,您可以使用react-timer-mixin。
反应定时器-MIXIN
使用裸setTimeout,setInterval,setImmediate和 requestAnimationFrame调用非常危险,因为如果你忘了 在卸载组件之前取消请求,您冒着风险 回调抛出异常。
如果您包含TimerMixin,那么您可以将呼叫替换为
setTimeout(fn, 500)
this.setTimeout(fn, 500)
{仅限前置this
。)一切都将为您妥善清理。
答案 1 :(得分:1)
清除this.interval
并在设置状态前进行检查。这样可以防止在卸载组件时设置状态。
componentWillUnmount() {
clearInterval(this.interval);
this.interval = null; // clear
}
rendering() {
// this.interval will be null when unmounting so avoid setting state:
if (this.interval) {
this.setState({
render: !this.state.render
});
}
}