代码之家  ›  专栏  ›  技术社区  ›  Or Assayag

反应警告:无法对未安装的组件调用setstate(或forceupdate)

  •  1
  • Or Assayag  · 技术社区  · 7 年前

    我有两个组件:
    订单-获取一些数据并显示。
    错误处理程序-如果服务器上发生错误,模式将显示并显示消息。
    错误处理程序组件正在警告订单组件

    我使用AXIOS包将数据加载到ORDERS组件中,并使用AXIOS拦截器设置错误的状态,并在组件卸载后弹出。

    当我前后导航到ORDERS组件时,有时会在控制台中出现错误:

    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)
    

    我试图用我以前的案例来解决它 React Warning: Can only update a mounted or mounting component 但在这里,我不能让检查员做一个公理标记。以前有人解决过这个问题吗?

    以下是我的组件:

    命令:

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

    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;
    
    3 回复  |  直到 6 年前
        1
  •  5
  •   Goran.it    6 年前

      state = {
        isMounted: false
      }
      componentDidMount() {
          this.setState({isMounted: true})
      }
      componentWillUnmount(){
          this.state.isMounted = false
      }
    

    if (this.state.isMounted) {
       this.setState({ loading: false, orders: fetchedOrders });
    }
    
        2
  •  2
  •   Javid Asgarov    7 年前

        3
  •  0
  •   dubes user2167877    7 年前

    unmount api.get() Orders

    ErrorBoundaries interceptors

    componentDidCatch ErrorHandler

    class ErrorHandler extends React.Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false };
      }
    
      componentDidCatch(error, info) {
        this.setState({ hasError: true, errorMessage : error.message });
      }
    
      render() {
        if (this.state.hasError) {
          return <Modal 
                        modalClosed={() => console.log('What do you want user to do? Retry or go back? Use appropriate method logic as per your need.')}>
                        {this.state.errorMessage ? this.state.errorMessage : null}
                    </Modal>
        }
        return this.props.children;
      }
    }
    

    class Orders extends Component {
        let cancel;
        state = {
            orders: [],
            loading: true
        }
    
        componentDidMount() {
            this.asyncRequest = api.get('/orders.json', {
            cancelToken: new CancelToken(function executor(c) {
                // An executor function receives a cancel function as a parameter
                cancel = c;
                })
            })
                .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 });
                    // please check the syntax, I don't remember if it is throw or throw new
                    throw error;
                });
        }
    
        componentWillUnmount() {
           if (this.asyncRequest) {
              cancel();
           }
        }
    
        render() {
            return (
                <div>
                    {this.state.orders.map(order => {
                        return (<Order
                            key={order.id}
                            ingrediencies={order.ingrediencies}
                            price={order.price} />);
                    })}
                </div>
            );
        }
    }
    

    <ErrorHandler>
       <Orders />
    </ErrorHandler>