来自Firebase的数据时,已卸载组件上的setState错误

时间:2019-05-17 10:53:34

标签: javascript reactjs react-redux

安装以下组件后,所有与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);
    }

1 个答案:

答案 0 :(得分:2)

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

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)
        );
    }