简体   繁体   中英

How to cleanup this useEffect hook

I am trying to fetch the user information from an authenticated AWS Cognito User Pool using the AWS Amplify libraries in react.

The following code gives me the following console error message after I logout from the app:

Warning: 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 a useEffect cleanup function. App@http://localhost:3000/static/js/main.chunk.js:211:82

Unfortunately I am not a front-end specialist and the react-hooks documentation are going over my head.

My first attempt was to create 2 separate useEffect blocks but it complained that user was not defined. What am I doing wrong here?

import React from "react";
import Amplify from "aws-amplify";
import {
  AmplifyAuthenticator,
  AmplifySignOut,
  withAuthenticator,
} from "@aws-amplify/ui-react";
import { AuthState, onAuthUIStateChange } from "@aws-amplify/ui-components";

Amplify.configure({
  Auth: {
    region: "...",
    userPoolId: "...",
    userPoolWebClientId: "...",
  },
});

const App = () => {
  const [authState, setAuthState] = React.useState();
  const [user, setUser] = React.useState();
  const [userGroup, setUserGroup] = React.useState();

  React.useEffect(() => {
    onAuthUIStateChange((nextAuthState, authData) => {
      setAuthState(nextAuthState);
      setUser(authData);
      if (authData !== undefined) {
        setUserGroup(authData.signInUserSession.accessToken.payload["cognito:groups"]);
      }
      console.log("user data: ", authData);
    });

  }, []);

  return authState === AuthState.SignedIn && user ? (
    <div>
      <AmplifySignOut />
      <div>Hello {user.username} from {userGroup}</div>
    </div>
  ) : (
    <AmplifyAuthenticator />
  );
};

export default withAuthenticator(App);

Your problem is trying to update the state after component unmount. The onAuthUIStateChange function seems to have been designed with the subscribe-unsubscribe architecture. It returns the unsubscribe function of this function itself. source code: https://github.com/aws-amplify/amplify-js/blob/master/packages/amplify-ui-components/src/common/helpers.ts#L58,L82

you can use it:

React.useEffect(() => {
const unsubscribe = onAuthUIStateChange((nextAuthState, authData) => {
    setAuthState(nextAuthState);
    setUser(authData);
    if (authData !== undefined) {
      setUserGroup(authData.signInUserSession.accessToken.payload["cognito:groups"]);
    }
    console.log("user data: ", authData);
  });

 return () => unsubscribe();
}, []);

Try this:

import React from "react";
import Amplify from "aws-amplify";
import {
  AmplifyAuthenticator,
  AmplifySignOut,
  withAuthenticator,
} from "@aws-amplify/ui-react";
import { AuthState, onAuthUIStateChange } from "@aws-amplify/ui-components";

Amplify.configure({
  Auth: {
    region: "...",
    userPoolId: "...",
    userPoolWebClientId: "...",
  },
});

const App = () => {
  const [didMount, setDidMount] = useState(false); 
  const [authState, setAuthState] = React.useState();
  const [user, setUser] = React.useState();
  const [userGroup, setUserGroup] = React.useState();

  React.useEffect(() => {
    setDidMount(true);
    onAuthUIStateChange((nextAuthState, authData) => {
      setAuthState(nextAuthState);
      setUser(authData);
      if (authData !== undefined) {
        setUserGroup(authData.signInUserSession.accessToken.payload["cognito:groups"]);
      }
      console.log("user data: ", authData);
    });
   return () => setDidMount(false);
  }, []);

   if(!didMount) {
   return null;
   }

  return authState === AuthState.SignedIn && user ? (
    <div>
      <AmplifySignOut />
      <div>Hello {user.username} from {userGroup}</div>
    </div>
  ) : (
    <AmplifyAuthenticator />
  );
};

export default withAuthenticator(App);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM