在已卸载的组件中发出有关setState的警告
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在已卸载的组件中发出有关setState的警告相关的知识,希望对你有一定的参考价值。
我收到这个错误:
warning.js:33警告:无法在卸载的组件上调用setState(或forceUpdate)。这是一个无操作,但它表示应用程序中存在内存泄漏。要修复,请取消componentWillUnmount方法中的所有订阅和异步任务。
但我没有使用componentWillUnMount方法。
我正在使用HOC来确保用户在访问其/ account帐户之前已通过身份验证。
这是路线:
<StyleRoute props={this.props} path="/account" component=
{RequireAuth(Account)} />
其中RequireAuth是HOC。这是HOC:
import { withRouter } from 'react-router';
export default function RequireAuth(Component) {
return class AuthenticatedComponent extends React.Component {
componentWillMount() {
this.checkAuth();
}
checkAuth() {
if ( ! this.props.isAuthenticated) {
this.props.history.push(`/`);
}
}
render() {
return this.props.isAuthenticated
? <Component { ...this.props } />
: null;
}
}
return withRouter(AuthenticatedComponent);
}
代码按预期工作,但是在呈现/ account时我收到了错误。正如您所注意到的,我的直接代码中没有任何地方存在componentWillUnMount方法。我真的不知道为什么这个警告不断出现,任何信息都会有所帮助。
更新5/23/18:
为了摆脱这个错误并且还有道具传递下来,我做了两件事:
1)我选择在父App组件中使用两个更高阶的函数,而不是使用HOC。一个高阶函数用于传递道具,另一个用于检查身份验证。我无法传递除浏览器历史之外的任何道具,因此下面是renderProps函数。
renderProps = (Component, props) => {
return (
<Component {...props} />
);
}
checkAuth = (Component, props) => {
if (props.isAuthenticated) {
return <Component {...props} />
}
if (!props.isAuthenticated) {
return <Redirect to='/' />
}
}
2)要使用这些,我必须在我的路线中使用渲染,而不是组件。
//I could pass props doing this, sending them through the above functions
<Route exact path="/sitter-dashboard" render={ () => this.checkAuth(SitterDashboard, this.props) } />
<Route exact path={"/account/user"} render={() => this.renderProps(User, this.props)} />
//I couldn't pass props doing this
<Route {...this.props} exact path="/messages" component={Messages} />
这是路由器与组件的文档,作为路由渲染方法:https://reacttraining.com/react-router/web/api/Route/route-render-methods
另外,这里是对Stack Overflow的一个很好的解释
最后,我使用了React Router 4文档中的代码作为我上面所做的模板。我确信下面的内容更清晰,但我还在学习,我所做的对我来说更有意义。
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
我之前有同样的错误,它是由一个使用ref标签的组件生成的,并且有一些手动操作。
看到这类错误的好习惯是吸引你的应用流程,看看你何时打电话给setState
。
如果我是你,我会改变的另一件事是componentDidMount
而不是componentWillMount
来检查一些数据。考虑到fb已弃用此功能。
此生命周期之前名为componentWillMount。该名称将继续有效,直到版本17.使用rename-unsafe-lifecycles codemod自动更新组件。
我有一个类似的问题,但我确实找出了相同的原因,所以这里是我遇到这个错误的代码片段。
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.
原因:
this.setState({ showLoader: true });
const { username } = this.state;
const URL = `https://api.github.com/users/${username}`;
try {
const { data } = await axios(URL);
this.props.apiData(data);
this.props.history.push("profile");
} catch (e) {
console.error(e);
}
this.setState({ showLoader: false });
正如您在代码片段中看到的那样,我正在做
this.props.history.push("profile");
在设置状态之前。
this.setState({ showLoader: false });
然后,在这种情况下,错误似乎是合法的,因为我重定向到另一个组件,然后在我之前的组件上设置状态。
解:
放置
this.setState({ showLoader: false });
在this.props.history.push("profile");
上方解决了这个问题。
我希望这有帮助。
以上是关于在已卸载的组件中发出有关setState的警告的主要内容,如果未能解决你的问题,请参考以下文章
为啥 FxCop 会在此 C# 代码中发出有关溢出 (CA2233) 的警告?
“警告:setState(...):只能更新已安装或已安装的组件”是啥意思?
React 警告:setState(...) 只能更新已安装或正在安装的组件
如何解决反应原生 EventEmitterListener 警告