在未安装的组件中react有关 setState 的警告

IT技术 reactjs
2021-03-28 18:18:43

我收到此错误:

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 方法。我真的不知道为什么这个警告不断弹出,任何信息都会有所帮助。


2018 年 5 月 23 日更新:

为了摆脱错误并仍然传递props,我做了两件事:

1)我选择在父 App 组件中使用两个高阶函数,而不是使用 HOC。一个高阶函数用于传递props,另一个是检查身份验证。我在传递浏览器历史之外的任何props时遇到了麻烦,因此下面的 renderProps 函数。

renderProps = (Component, props) => {
  return (
      <Component {...props} />
    );
}

checkAuth = (Component, props) => {
    if (props.isAuthenticated) {
        return <Component {...props} />
    }
    if (!props.isAuthenticated) {
        return <Redirect to='/' />
    }
}

2) 要使用这些,我必须在我的 Route 中进行用户渲染,而不是组件。

//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 }
          }}
        />
      )
    }
  />
);
2个回答

前段时间我遇到了同样的错误,它是由使用 ref 标记的组件生成的,并且有一些手动操作。

查看此类错误的一个好做法是绘制您的应用程序流程并查看您何时调用setState.

如果我是你,我会改变的另一件事是componentDidMount而不是componentWillMount检查一些数据。考虑到 fb 已弃用此功能。

这个生命周期以前被命名为 componentWillMount。该名称将继续有效,直到版本 17。使用 rename-unsafe-lifecycles codemod 自动更新您的组件。

Reactjs 组件文档

我有一个类似的问题,但我确实找出了背后的原因,所以这里是我遇到这个错误的代码片段。

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

然后在这种情况下err似乎是合法的,因为我正在重定向到不同的组件,然后在我之前的组件上设置状态。

解决方案:

放置

this.setState({ showLoader: false });

以上this.props.history.push("profile");解决了问题。

我希望这有帮助。