首页 > 解决方案 > 使用来自 Firebase 的数据时,未安装组件上的 setState 错误

问题描述

安装下面的组件后,与 Firebase 相关的所有内容都可以正常工作。更新 Firebase 中的数据时会出现此问题。然后我导航到不同的路线,因此卸载此组件并发生 setState 错误。

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component

我尝试在 componentWillUnmount 中关闭 Firebase 功能,但我似乎仍然遇到错误。任何帮助,将不胜感激

   constructor() {
        super();
        this.state = {
            firebaseData: {}
        };
    }
    componentDidMount() {
        const { referenceId } = this.props.episode || '';
        if (referenceId) {
            this.getFirebaseData(this.removeDissallowedChars(referenceId));
        }
    }
    componentWillReceiveProps(nextProps) {
        if (this.props.values.referenceId !== nextProps.values.referenceId) {
            this.setState({
                referenceId: nextProps.values.referenceId,
            }, this.fetchWorkflows);
        }
    }
    getFirebaseData(refId) {
        const database = firebase.database().ref(`workflows/sky/${refId}`);
        database.on('value', snapshot => {
            this.setState({ firebaseData: snapshot.val() });
        }, error =>
            console.log(error)
        );
    }
    componentWillUnmount(refId) {
        const database = firebase.database().ref(`workflows/sky/${refId}`);
        database.off();
    }
    removeDissallowedChars(badRefId) {
        /**
         * BE strip characters that Firebase doesn't allow.
         * We need to do the same. Reference id will only contain the characters listed below.
         * Change needed in FE as some of our reference id's currently contain period characters.
         **/
        return badRefId.replace(/[^A-Za-z0-9-:/]+/g, '-');
    }
    fetchWorkflows() {
        const { referenceId } = this.state;
        this.props.fetchWorkflows(referenceId);
    }

标签: javascriptreactjsreact-redux

解决方案


您可以有一个类变量来跟踪您的组件是否已安装。看起来像这样:

constructor() {
    //...
    this._mounted = false;
}

componentDidMount() {
    this._mounted = true;
    //...
}

componentWillUnmount() {
    //...
    this._mounted = false;
}

然后在异步请求后设置状态的任何地方,您可以放置​​一个 if 语句来检查是否_mounted为真。

在你的情况下:

    getFirebaseData(refId) {
        const database = firebase.database().ref(`workflows/sky/${refId}`);
        database.on('value', snapshot => {
            // Check if component is still mounted.
            if (this._mounted) {
                this.setState({ firebaseData: snapshot.val() });
            }
        }, error =>
            console.log(error)
        );
    }

推荐阅读