我的测试中有以下警告:
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()
中完成的,因此不应该抛出此错误。
我应该在哪里检查以解决此警告?
谢谢!
答案 0 :(得分:0)
这有点棘手,但这就是发生的事情:
在初始安装组件时,会调用componentDidMount
并触发Authentication.getUser
来电。由于它是异步的,它会立即运行,而是被添加到javascript事件循环中。此时,代码继续。由于auth调用尚未实际完成,因此您还没有用户。在您的渲染方法中,如果没有用户,您可以指定将查看器重定向到/auth/login
。由于是这种情况,您将被重定向,并且您的组件最终将卸载。
你知道我要去哪里吗?
事件循环最终决定不需要运行其他同步代码,并为该驻留身份验证调用提供触发机会。它做了它的事情,并尝试根据有/不是用户的位置更新状态。但组件不再存在。 :(
然后你从伟大的反应之神那里得到了这个好消息。但你是一个程序员,你从中学习,这种情况开始越来越少。
您需要组件状态来跟踪您的身份验证呼叫是否已完成。只有在呼叫完成后,您才应该尝试检查是否有用户。只有这样,如果用户不在场,您应该重定向。
也许一个isFetchingUser
州的财产就足够了?然后,一旦isFetchingUser
false
且user
不存在,您就会重定向,否则如果isFetchingUser
为true
,您可以显示加载消息,微调器或者只是一个白色的屏幕,因为您的异步调用应该非常快。
答案 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
componentDidMount
内f.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
,因为您的组件已卸载而无法执行。
因此,您将获得警告。