反应警告:无法在未安装的组件上调用setState(或forceUpdate)

OrA*_*yag 1 javascript reactjs axios

我有2个组件:
订单-获取一些数据并显示它。
ErrorHandler-如果服务器上发生某些错误,将显示模式并显示一条消息。
ErrorHandler组件正在扭曲订单组件

我正在使用axios包在Orders组件中加载数据,并且使用axios拦截器来设置有关错误的状态,并在卸载组件后弹出。

当我前后导航到订单组件时,有时会在控制台中收到错误消息:

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.
    in Orders (at ErrorHandler.jsx:40)
    in Auxiliary (at ErrorHandler.jsx:34)
    in _class2 (created by Route)
Run Code Online (Sandbox Code Playgroud)

我试图通过我以前的案例来解决它React警告:只能更新已安装的或正在安装的组件,但在这里我不能由检查员制作axios令牌。有人解决过这个问题吗?

这是我的组件:

订单:

import React, { Component } from 'react';
import api from '../../api/api';
import Order from '../../components/Order/Order/Order';
import ErrorHandler from '../../hoc/ErrorHandler/ErrorHandler';

class Orders extends Component {
    state = {
        orders: [],
        loading: true
    }

    componentDidMount() {
        api.get('/orders.json')
            .then(response => {
                const fetchedOrders = [];
                if (response && response.data) {
                    for (let key in response.data) {
                        fetchedOrders.push({
                            id: key,
                            ...response.data[key]
                        });
                    }
                }
                this.setState({ loading: false, orders: fetchedOrders });
            })
            .catch(error => {
                this.setState({ loading: false });
            });
    }

    render() {
        return (
            <div>
                {this.state.orders.map(order => {
                    return (<Order
                        key={order.id}
                        ingrediencies={order.ingrediencies}
                        price={order.price} />);
                })}
            </div>
        );
    }
}

export default ErrorHandler(Orders, api);
Run Code Online (Sandbox Code Playgroud)

ErrorHandler:

import React, { Component } from 'react';
import Auxiliary from '../Auxiliary/Auxiliary';
import Modal from '../../components/UI/Modal/Modal';

const ErrorHandler = (WrappedComponent, api) => {
    return class extends Component {
        requestInterceptors = null;
        responseInterceptors = null;
        state = {
            error: null
        };

        componentWillMount() {
            this.requestInterceptors = api.interceptors.request.use(request => {
                this.setState({ error: null });
                return request;
            });
            this.responseInterceptors = api.interceptors.response.use(response => response, error => {
                this.setState({ error: error });
            });
        }

        componentWillUnmount() {
            api.interceptors.request.eject(this.requestInterceptors);
            api.interceptors.response.eject(this.responseInterceptors);
        }

        errorConfirmedHandler = () => {
            this.setState({ error: null });
        }

        render() {
            return (
                <Auxiliary>
                    <Modal
                        show={this.state.error}
                        modalClosed={this.errorConfirmedHandler}>
                        {this.state.error ? this.state.error.message : null}
                    </Modal>
                    <WrappedComponent {...this.props} />
                </Auxiliary>
            );
        }
    };
};

export default ErrorHandler;
Run Code Online (Sandbox Code Playgroud)

Gor*_*.it 8

我认为这是由于异步调用触发了setState,即使未安装组件也可能发生。为了防止这种情况的发生,您可以使用一些标志:

  state = {
    isMounted: false
  }
  componentDidMount() {
      this.setState({isMounted: true})
  }
  componentWillUnmount(){
      this.state.isMounted = false
  }
Run Code Online (Sandbox Code Playgroud)

然后使用以下代码包装setState调用:

if (this.state.isMounted) {
   this.setState({ loading: false, orders: fetchedOrders });
}
Run Code Online (Sandbox Code Playgroud)

  • 来自react docs:您不应在componentWillUnmount()中调用setState(),因为永远不会重新渲染该组件。卸载组件实例后,将不再安装它。 (2认同)