I posted this on StackOverflow, however, there’s still no solution.
When I logout of my meteor app I get memory leak error. It seems to happen about 50% of the time and I can’t figure out what I’m doing wrong here. Can someone please explain what’s wrong with my method. I think it has something to do with the way I’m controlling the authenticated routes.
Error message
Can’t perform a React state update 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.
App details
Metoer, React, React-Router V4
Path: LogoutButton.jsx
class LogoutButton extends React.Component {
constructor(props) {
super(props);
this.state = {
logoutRedirect: false
};
this.handleLogout = this.handleLogout.bind(this);
}
handleLogout = e => {
e.preventDefault();
Meteor.logout(err => {
if (err) {
console.log('err', err);
} else {
this.setState({ logoutRedirect: true });
}
});
};
render() {
const logoutRedirect = this.state;
if (logoutRedirect.logoutRedirect) {
return <Redirect to="/" />;
}
return (
<button
type="button"
className="btn btn-link dropdown-item text-dark"
onClick={this.handleLogout}
>
<FontAwesomeIcon icon={faSignOutAlt} className="mr-2 text-dark" />
Logout
</button>
);
}
}
Path: IsAuthenticatedRouteNavbar
function IsAuthenticatedRouteNavbar() {
return (
<nav>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<NavLink className="nav-link" exact to="/">
Home
</NavLink>
</li>
<li className="nav-item">
<LogoutButton />
</li>
</ul>
</div>
</nav>
);
}
Path: IsAuthenticatedRoute.jsx
const IsAuthenticatedRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={props => {
const { loading, profile } = rest;
const isAuth = profile && profile.isAuth;
if (loading) {
if (isAuth) {
return (
<React.Fragment>
<IsAuthenticatedRouteNavbar /> <Component {...rest} />
</React.Fragment>
);
}
return (
<p className="text-center pt-5 mt-5">
You don't have the right account to access this page. Please return to your{' '}
<Link to="/login">dashboard</Link>.
</p>
);
}
return <span>...</span>;
}}
/>
);
};
const IsAuthenticatedRouteContainer = withTracker(props => {
const profileHandle = Meteor.subscribe('publish-user-profile');
const loadingProfileHandle = !profileHandle.ready();
const profile = Profiles.findOne({ userId: Meteor.userId() });
const loading = !loadingProfileHandle;
return {
loading,
profile
};
})(IsAuthenticatedRoute);
Path: PublicNavbar
function PublicNavbar(props) {
const { isAdmin, isLoggedIn } = props;
return (
<nav>
<div>
<ul className="navbar-nav ml-auto">
{isLoggedIn ? (
<React.Fragment>
{isAdmin ? (
<React.Fragment>
<DropdownItem>
<NavLink className="nav-link" to="/admin/accounts">
Accounts
</NavLink>
</DropdownItem>
</React.Fragment>
) : null}
<LogoutButton />
</React.Fragment>
) : (
<li className="nav-item">
<NavLink className="nav-link" exact to="/login">
Login
</NavLink>
</li>
)}
</ul>
</div>
</nav>
);
}
const PublicNavbarContainer = withTracker(() => {
let loading;
let profile;
if (Meteor.isClient) {
const profileHandle = Meteor.subscribe('publish-user-profile');
const loadingProfileHandle = !profileHandle.ready();
profile = Profiles.findOne({ userId: Meteor.userId() });
loading = !loadingProfileHandle && !!profile;
}
return {
loading,
isAdmin: profile && profile.isAdmin
};
})(PublicNavbar);
Path: IsPublicRoute
const IsPublicRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props => {
let isLoggedIn = false;
if (Meteor.isServer) {
isLoggedIn = props && props.staticContext && props.staticContext.checkIfUserIsLoggedIn;
}
if (Meteor.isClient) {
isLoggedIn = Meteor.userId() !== null;
}
return (
<React.Fragment>
<PublicNavbar isLoggedIn={isLoggedIn} />
<Component {...props} />
</React.Fragment>
);
}}
/>
);