Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
794 views
in Technique[技术] by (71.8m points)

reactjs - React warning about setState in unmounted component

I'm getting this error:

warning.js:33 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.

But I'm not using a componentWillUnMount method.

I'm using a HOC to make sure the user is authenticated before accessing their /account route.

Here's the Route:

<StyleRoute props={this.props} path="/account" component= 
{RequireAuth(Account)} />

where RequireAuth is the HOC. Here's the 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);
}

The code works as intended, but I'm getting that error when /account is rendered. As you notice, nowhere in my direct code is there an componentWillUnMount method. I'm really at a loss for why this warning keeps popping up and any info would help.


Update 5/23/18:

To get rid of the error and still have props pass down, I did two thing:

1) I opted for a having two higher order functions in parent App component instead of using the HOC. One higher order function is for passing props and the other is to check authentication. I was having trouble passing any props other than the browser history, hence the renderProps function below.

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

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

2) To use these, I had to user render in my Route, as opposed to component.

//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} />

Here's the documentation on router vs component as a Route render method: https://reacttraining.com/react-router/web/api/Route/route-render-methods

Also, here's a good explanation on Stack Overflow

Finally, I used this code from the React Router 4 documentation as a template for what I did above. I'm sure the below is cleaner, but I'm still learning and what I did makes a bit more sense to me.

const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
  {...rest}
  render={props =>
  fakeAuth.isAuthenticated ? (
       <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had the same error time ago and it was generated by a component which was using ref tag, and there was some manual manipulation.

A good practice to see these kind of errors is drawing your app flow and see when your are calling setState.

Another thing I would change if I were you is componentDidMount instead of componentWillMount to check some data. Take into account fb deprecated this functionality.

This lifecycle was previously named componentWillMount. That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.

Reactjs component documentation


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...