更新已安装或安装组件警告

时间:2018-03-12 17:28:19

标签: javascript reactjs

我的测试中有以下警告:

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

Please check the code for the ProtectedRoute component.

所以我检查了我的ProtectedRoute组件。此组件基于Route中的react-router组件构建,并检查用户是否在呈现路由之前已登录。这是组件代码:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Redirect, Route } from 'react-router-dom';
import { Authentication } from 'local-authentication-service';

const renderMergedProps = (component, ...otherProps) => {
  const finalProps = Object.assign({}, ...otherProps);
  return (
    React.createElement(component, finalProps)
  );
};

class ProtectedRoute extends Component {
  constructor() {
    super();
    this.state = { loading: true };
  }

  async componentDidMount() {
    try {
      const user = await Authentication.getUser();
      this.setState({ user, loading: false });
    } catch (e) {
      this.setState({ loading: false });
    }
  }

  render() {
    const { loading, user } = this.state;
    const { component, ...otherProps } = this.props;

    if (loading) return <div>Loading...</div>;

    return user ? <Route render={routeProps => renderMergedProps(component, routeProps, { user }, otherProps)} /> : <Redirect to="/auth/login" />;
  }
}

ProtectedRoute.propTypes = {
  component: PropTypes.oneOfType([
    PropTypes.element,
    PropTypes.func,
  ]).isRequired,
};

export default ProtectedRoute;

据我所知,唯一的状态更改是在componentDidMount()中完成的,因此不应该抛出此错误。 我应该在哪里检查以解决此警告?

谢谢!

2 个答案:

答案 0 :(得分:0)

当您的异步身份验证调用完成时,您已经将用户重定向到/ auth / login和unmounted ProtectedRoute。当auth调用最终完成时,它会尝试更新ProtectedRoute的状态。这就是React给你的好消息,说你正在尝试更新不再存在的组件。阅读详情:)

这有点棘手,但这就是发生的事情:

在初始安装组件时,会调用componentDidMount并触发Authentication.getUser来电。由于它是异步的,它会立即运行,而是被添加到javascript事件循环中。此时,代码继续。由于auth调用尚未实际完成,因此您还没有用户。在您的渲染方法中,如果没有用户,您可以指定将查看器重定向到/auth/login。由于是这种情况,您将被重定向,并且您的组件最终将卸载。

你知道我要去哪里吗?

事件循环最终决定不需要运行其他同步代码,并为该驻留身份验证调用提供触发机会。它做了它的事情,并尝试根据有/不是用户的位置更新状态。但组件不再存在。 :(

然后你从伟大的反应之神那里得到了这个好消息。但你是一个程序员,你从中学习,这种情况开始越来越少。

你怎么能避免这种情况?

您需要组件状态来跟踪您的身份验证呼叫是否已完成。只有在呼叫完成后,您才应该尝试检查是否有用户。只有这样,如果用户不在场,您应该重定向。

也许一个isFetchingUser州的财产就足够了?然后,一旦isFetchingUser falseuser不存在,您就会重定向,否则如果isFetchingUsertrue,您可以显示加载消息,微调器或者只是一个白色的屏幕,因为您的异步调用应该非常快。

答案 1 :(得分:0)

  

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

componentDidMount生命周期之前,会调用render

render

 return user ? 
 <Route render={routeProps => renderMergedProps(component, routeProps, { user }, otherProps)} /> 
 : <Redirect to="/auth/login" />;

最初user被评估为false,导致Redirect路由被调用。因此,当前ProtectedRoute组件已卸载。

但与此同时,您正在设置setState componentDidMountf.inputs "Attachment", :multipart => true do f.input :cover_page, :as => :file, :hint => image_tag(f.object.cover_page.url) f.input :cover_page_cache, :as => :hidden end ,因为您的组件已卸载而无法执行。

因此,您将获得警告。