【问题标题】:How to cleanup this useEffect hook如何清理这个 useEffect 钩子
【发布时间】:2021-03-18 15:29:22
【问题描述】:

我正在尝试使用响应中的 AWS Amplify 库从经过身份验证的 AWS Cognito 用户池中获取用户信息。

在我从应用程序注销后,以下代码会显示以下控制台错误消息:

警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。 app@http://localhost:3000/static/js/main.chunk.js:211:82

不幸的是,我不是前端专家,react-hooks 文档让我头疼。

我的第一次尝试是创建 2 个单独的 useEffect 块,但它抱怨 user 未定义。我在这里做错了什么?

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

【问题讨论】:

  • 可能是组件挂载前的onAuthUIStateChange调用,所以在回调setUserGroup, setAuthState, setUser中会导致控制台报错。 onAuthUIStateCHange 是做什么的?当节点包中的AuthState发生变化时是否调用?
  • 这是我能找到的关于这个回调的尽可能多的文档。 docs.amplify.aws/ui/auth/authenticator/q/framework/…
  • 没有return () 可以试试吗?
  • 您没有在监听事件,您只是使用了在 authState 更改时触发的方法。所以 useEffect 没有什么要清除的。

标签: javascript reactjs react-hooks aws-amplify


【解决方案1】:

您的问题是在组件卸载后尝试更新状态。 onAuthUIStateChange 函数似乎是使用订阅-取消订阅架构设计的。 它返回此函数本身的取消订阅函数。 源代码:https://github.com/aws-amplify/amplify-js/blob/master/packages/amplify-ui-components/src/common/helpers.ts#L58,L82

你可以使用它:

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();
}, []);

【讨论】:

    【解决方案2】:

    试试这个:

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

    【讨论】:

    • 您的回答不能解决这个问题。因为问题源于卸载后调用回调。
    猜你喜欢
    • 2019-09-09
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 2023-01-08
    • 2020-03-05
    • 2020-04-09
    • 1970-01-01
    • 2022-11-15
    相关资源
    最近更新 更多