我是 ReactJS 的初学者。我想构建一个供我自己使用的 React 应用程序。事实上,在我的网页中,我有三个按钮,一个用于增加我的 firebase 数据库中的一个字段,一个用于增加我数据库中的另一个字段,最后一个用于清理这两个字段和 UI。 这些按钮有效,但是当我离开页面转到另一个页面时,控制台显示这些错误“index.js:1446 Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op , 但它表明您的应用程序中存在内存泄漏。要解决此问题,请取消 componentWillUnmount 方法中的所有订阅和异步任务。
所以,我在网上搜索了一个解决方案,我只找到了告诉我设置一个变量 isMounted 并在 componentDidMount 和 componentWillUnmount 中更改她的解决方案。但问题仍然存在。所以我回到了我的第一个代码。 感谢您的帮助,抱歉英语不好,我是法国人。
import React, { Component } from 'react';
import { Button } from 'antd';
import Nav from '../component/Nav';
import firebase from 'firebase';
import config from '../config/config';
class Recap extends Component{
constructor(){
super();
!firebase.apps.length ? this.app = firebase.initializeApp(config) : this.app = firebase.app();
this.database = this.app.database().ref().child('scoreMensuel');
this.state={
scoreMensuel : {
},
loading:true,
}
this.style={
styleTable:{width:'50%'},
styleCell:{border:'1px solid black'},
styleScoreField:{border:'1px solid black', height:'300px'}
}
}
componentWillMount(){
this.database.on('value', snapshot => {
this.setState({
scoreMensuel: snapshot.val()
});
this.setState({loading:false});
});
}
addScore = event =>{
console.log(event.target.id);
if(event.target.id === 'entrainementOk'){
this.database.child('TeamGainz').transaction(function(currentValue) {
return ( (currentValue) + 1);
}, function(err, committed, ss) {
if( err ) {
return err;
}
});
}else if(event.target.id === 'entrainementNotOk'){
this.database.child('TeamKeh').transaction(function(currentValue) {
return ((currentValue) + 1);
}, function(err, committed, ss) {
if( err ) {
return err;
}
});
}
}
clearScore = event =>{
this.database.child('TeamGainz').transaction(function(currentValue) {
return ( (currentValue) - (currentValue));
});
this.database.child('TeamKeh').transaction(function(currentValue) {
return ( (currentValue) - (currentValue));
});
}
render(){
const loading = this.state.loading;
if(loading){
return(<h1>Chargement...</h1>)
}
return(
<div className="reacp">
<Nav/>
<h1>Récapitulatif Mensuel</h1>
<table style={this.style.styleTable}>
<tbody className="tableauTeam">
<tr>
<td style={this.style.styleCell}>Team Gainz</td>
<td style={this.style.styleCell}>Team Keh</td>
</tr>
<tr>
<td
style={this.style.styleScoreField} id='idTeam1'> {this.state.scoreMensuel.TeamGainz}
<Button type='danger' id='entrainementOk'onClick={this.addScore}>Entraînement Effectué</Button>
</td>
<td style={this.style.styleScoreField} id='idTeam2'>{this.state.scoreMensuel.TeamKeh}
<Button type='danger' id='entrainementNotOk' onClick={this.addScore}>Entraînement Raté</Button>
</td>
</tr>
</tbody>
</table>
<Button type='primary' style={{margin:'10px'}} onClick={this.clearScore}>Nettoyer le tableau</Button>
</div>
);
}
}
export default Recap;
即使此警告不影响按钮,我也想了解为什么会出现此警告。
最佳答案
您不应该在 componentWillMount
中调用 setState
。相反,在 componentDidMount
中调用它:
componentWillMount(){
// ^^^^^^^^^^^^^^^ change this to componentDidMount
this.database.on('value', snapshot => {
this.setState({
scoreMensuel: snapshot.val()
});
this.setState({loading:false});
});
}
这是一个问题的原因是因为调用 setState
会触发一个重新渲染器,如果我们在 componentWillMount
中调用它,我们可能会触发一个未安装的重新渲染渲染流程中任何位置的组件。
由于您是基于(大概)异步回调触发状态更改,这意味着您在数据何时到达和 React 渲染何时之间存在竞争条件。
事实上,React has deprecated componentWillMount
and currently ships with UNSAFE_componentWillMount()
react 文档:
Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead.
关于javascript - 如何在未安装的组件上修复 'index.js:1446 Warning: Can' t 调用 setState(或 forceUpdate)...“在 ReactJS 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54150211/