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 } }} /> ) } /> );
Seeing called setState() on an unmounted component in your browser console means the callback for an async operation is still running after a component's removed from the DOM. This points to a memory leak caused by doing redundant work which the user will never benefit from.
To solve the "Warning: Can't perform a React state update on an unmounted component", declare an isMounted boolean in your useEffect hook that is used to track whether the component is mounted. A component's state should only be updated if the component is mounted.
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.
In the happy path you won't have any issues — setState will execute, and your state will successfully update. But if you invoke setState within the context of an asynchronous operation, then you might run into the React warning “Can't perform a React state update on an unmounted component”.
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
I had a similar problem, but I did figure out the reason behind the same, so here is the snippet of code where I was encountering this err.
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.
Cause:
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 });
As you can see in the code-snippet, I was doing
this.props.history.push("profile");
before setting the state.
this.setState({ showLoader: false });
And then err seems to be legit in this case as I was redirecting to a different component and then setting the state on the component I was earlier.
Solution:
By placing
this.setState({ showLoader: false });
above the this.props.history.push("profile");
solved the problem.
I hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With