简体   繁体   English

如何修复“index.js:1446 警告:无法在未安装的组件上调用 setState(或 forceUpdate)...”在 ReactJS 中

[英]How to fix 'index.js:1446 Warning: Can't call setState (or forceUpdate) on an unmounted component..." in ReactJS

I am a beginner in ReactJS.我是 ReactJS 的初学者。 I want to build a react app for my own use.我想构建一个供我自己使用的 React 应用程序。 Indeed, in my web page, I have three button, one for increment a field in my firebase database, on in order to increment an other field in my database and finally on to clean the two fields and the UI.事实上,在我的网页中,我有三个按钮,一个用于增加我的 firebase 数据库中的一个字段,用于增加我的数据库中的另一个字段,最后清理这两个字段和 UI。 These button work but when I leave the page to go to another and I come, the console show these error "index.js:1446 Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method".这些按钮有效,但是当我离开页面转到另一个页面时,控制台显示这些错误“index.js:1446 警告:无法在未安装的组件上调用 setState(或 forceUpdate)。这是一个空操作,但它表示您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务”。

So, I searched a solution in the internet, and I only found solutions wich tell me to set a variable isMounted and change her in componentDidMount and componentWillUnmount.所以,我在互联网上搜索了一个解决方案,我只找到了告诉我设置变量 isMounted 并在 componentDidMount 和 componentWillUnmount 中更改她的解决方案。 But the problem is still here.但问题仍然在这里。 So I returned to my first code.所以我回到了我的第一个代码。 Thanks for your help, sorry for bad english, Iam french.感谢您的帮助,抱歉英语不好,我是法国人。

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;

Even if this warning don't affect buttons, I want to understand why this warning comes.即使此警告不影响按钮,我也想了解为什么会出现此警告。

You shouldn't call setState in componentWillMount .您不应该在componentWillMount调用setState Instead, call it in componentDidMount :相反,在componentDidMount调用它:

componentWillMount(){
// ^^^^^^^^^^^^^^^ change this to componentDidMount
    this.database.on('value', snapshot => {
        this.setState({
            scoreMensuel: snapshot.val()
        });
        this.setState({loading:false});
    });
}

The reason this is a problem is because calling setState triggers a re-renderer and if we call it in componentWillMount , we might trigger a re-render of an unmounted component anywhere in the rendering flow.这是一个问题的原因是因为调用setState会触发重新渲染器,如果我们在componentWillMount调用它,我们可能会在渲染流的任何位置触发未安装组件的重新渲染。

Since you are triggering the change in state based on a (presumably) async callback, this means that you have a race-condition between when does your data arrive and when does React render.由于您是基于(大概)异步回调触发状态更改,这意味着您在数据到达时间和 React 渲染时间之间存在竞争条件。

In fact, React has deprecated componentWillMount and currently ships with UNSAFE_componentWillMount()事实上, React 已经弃用了componentWillMount并且目前带有UNSAFE_componentWillMount()

React docs:反应文档:

Avoid introducing any side-effects or subscriptions in this method.避免在此方法中引入任何副作用或订阅。 For those use cases, use componentDidMount() instead.对于这些用例,请改用 componentDidMount()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 反应-警告:无法在未安装的组件上调用setState(或forceUpdate) - React - Warning: Can't call setState (or forceUpdate) on an unmounted component 反应警告:无法在未安装的组件上调用 setState(或 forceUpdate) - React Warning: Can't call setState (or forceUpdate) on an unmounted component 警告:无法在React Native中的已卸载组件上调用setState(或forceUpdate) - Warning: Can't call setState (or forceUpdate) on an unmounted component in React Native 警告:无法在卸载的组件上调用setState(或forceUpdate) - Warning: Can't call setState (or forceUpdate) on an unmounted component 无法在卸载的组件上调用setState(或forceUpdate) - Can't call setState (or forceUpdate) on an unmounted component 如何解决:无法在 React-Native 中的未挂载组件警告上调用 setState(或 forceUpdate)? - How to solve: Can't call setState(or forceUpdate) on an unmounted component warning in React-Native? 有人知道如何解决此错误:无法在已卸载的组件上调用setState(或forceUpdate)吗? - Does somebody know how to fix this error: Can't call setState (or forceUpdate) on an unmounted component…? 无法在已卸载的组件上调用setState(或forceUpdate)。 应对 - Can't call setState (or forceUpdate) on an unmounted component. React 多步骤表单:无法在已卸载的组件上调用setState(或forceUpdate) - multi-step form: Can't call setState (or forceUpdate) on an unmounted component 无法在已卸载的组件上调用setState(或forceUpdate)。 这是空操作,但表示您的应用程序内存泄漏 - Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM