react警告:只能更新已安装或正在安装的组件

IT技术 javascript reactjs
2022-07-09 00:18:31

我使用 react router dom 中的 Route 组件在它们之间路由了 2 个组件。componentDidMount其中一个组件在事件(使用 axios 包)时从虚拟 API 服务器获取数据,代码如下:

    componentDidMount() {
    axios.get('/posts')
        .then(response => {
            const posts = response.data.slice(0, 4);
            const updatedPost = posts.map(post => {
                return {
                    ...post,
                    author: 'Max'
                };
            });
            this.setState({ posts: updatedPost });
        })
        .catch(error => {
            console.log(error);
        });
}

错误是,当我从一个组件重定向到另一个组件的速度太快,或者甚至不是那么快时,我会在控制台上收到以下警告:

警告:只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了 setState、replaceState 或 forceUpdate。这是一个无操作。

请检查帖子组件的代码。

我能做些什么来解决这个问题?我试图通过以下方式弄清楚: setState(...): Can only update amounted ormounting component。这通常意味着您在未安装的组件上调用了 setState()。这是一个空操作 ,但我真的不明白何时传递 ref 以及如何传递。如果有人可以举例说明如何解决此问题,那就太好了。谢谢!

2个回答

react警告是有效的。当你调用一个setState已经unmounted. 如果组件出于某种原因(例如用户导航离开) ,则处理它的正确方法是cancel数据获取请求。unmounted

以下是来自官方博客的建议。利用componentWillUnmount生命周期

class ExampleComponent extends React.Component {
  state = {
    externalData: null,
  };

  componentDidMount() {
    this._asyncRequest = asyncLoadData().then(
      externalData => {
        this._asyncRequest = null;
        this.setState({externalData});
      }
    );
  }

  componentWillUnmount() {
    if (this._asyncRequest) {
      this._asyncRequest.cancel();
    }
  }

  render() {
    if (this.state.externalData === null) {
      // Render loading state ...
    } else {
      // Render real UI ...
    }
  }
}

看起来 Axios支持“可取消”请求。

我通过 dubes 的回答解决了这个问题!非常感谢,这是我的代码,效果很好!

const CancelToken = axios.CancelToken;
let cancel;

class Posts extends Component {

    asyncRequest = null;
    state = {
        posts: []
    };

    componentDidMount() {
        this.asyncRequest = axios.get('/posts', {
            cancelToken: new CancelToken(function executor(c) {
                // An executor function receives a cancel function as a parameter
                cancel = c;
            })
        })
            .then(response => {
                const posts = response.data.slice(0, 4);
                const updatedPost = posts.map(post => {
                    return {
                        ...post,
                        author: 'Max'
                    };
                });
                this.setState({ posts: updatedPost });
            })
            .catch(error => {
                console.log(error);
            });
    }

    componentWillUnmount() {
        if (this.asyncRequest) {
            cancel();
        }
    }
}