【问题标题】:Warning to make a cleanup function in useEffect() occurs occasionally偶尔会出现在 useEffect() 中创建清理功能的警告
【发布时间】:2020-11-12 14:27:22
【问题描述】:

我正在使用 AWS-Amplify,当用户退出时我收到警告:

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.

它提到它出现在 Profile.tsx 文件中,这是 useEffect() 钩子。

但问题是有时会发生错误。

我一直在测试它,它来来去去,我不知道为什么会这样。

 function Profile() {

  const [user, setUser] = useState<IIntialState | null>(null);

  useEffect(() => {
    checkUser();
    Hub.listen("auth", data => {
      const { payload } = data;
      if (payload.event === "signOut") {
        setUser(null);
      }
    });
  }, []);

  async function checkUser() {
    try {
      const data = await Auth.currentUserPoolUser();
      const userInfo = { username: data.username, ...data.attributes };
      console.log(userInfo);
      setUser(userInfo);
    } catch (err) {
      console.log("error: ", err);
    }
  }
  function signOut() {
    Auth.signOut().catch(err => console.log("error signing out: ", err));
  }
  if (user) {
    return (
      <Container>
        <h1>Profile</h1>
        <h2>Username: {user.username}</h2>
        <h3>Email: {user.email}</h3>
        <h4>Phone: {user.phone_number}</h4>
        <Button onClick={signOut}>Sign Out</Button>
      </Container>
    );
  }
  return <Form setUser={setUser} />;
}

【问题讨论】:

    标签: reactjs aws-amplify


    【解决方案1】:

    我发生这种情况是因为您卸载了组件,但您仍然有订阅。

    React useEffect提供卸载功能:

      useEffect(() => {
        Hub.listen("auth", func);
        return () => {
        // unsubscribe here
         Hub.remove("auth", signOut)
        };
     });
    

    你的 Hub 类有 remove 方法

    remove(channel: string | RegExp, listener: HubCallback): void
    

    useEffect返回函数中删除您的订阅

    Hub.remove()

    【讨论】:

    • 我可以将Hub.remove() 放在清理函数中吗?另外,我还需要传递什么作为channellistener
    • 您已订阅 'auth' Hub.listen("auth", func)。在网络中检查您的 ws 选项卡,订阅应该仍然存在 onUnmount 组件。尝试取消订阅 Hub.remove('auth')
    • 还可能造成内存泄漏,每次渲染组件时都会有新的订阅,但永远不会取消订阅
    • 是的,在返回函数中输出它。请检查我的更新
    • remove() 接受 2 个参数。
    【解决方案2】:

    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.

    信息很简单。我们正在尝试更改组件的状态,即使它已被卸载且不可用。

    发生这种情况的原因有很多,但最常见的是我们没有取消订阅 websocket 组件,或者这是在异步操作完成之前卸载。要解决这个问题,您可以这样做:

     useEffect(() => {
        checkUser();
        //check howto remove this listner in aws documentation  
        const listner= Hub.listen("auth", data => {
          const { payload } = data;
          if (payload.event === "signOut") {
            setUser(null);
          }
        });
    
        //this return function is called on component unmount 
        return ()=>{/* romve the listner here */}
      }, []);
    
    

    或者采用这种简单的方法。

     useEffect(() => {
        let mounted =true
        Hub.listen("auth", data => {
          const { payload } = data;
          if (payload.event === "signOut" && mounted ) {
            setUser(null);
          }
        });
    
    
         //this return function is called on component unmount 
        return ()=>{mounted =false }
      }, []);
    
    

    阅读更多关于this here的信息。

    【讨论】:

    • 这个也可以,但我选择了另一个,因为它更适合我使用 AWS-Amplify 的特定用例。
    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 2021-02-07
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    • 2021-10-08
    相关资源
    最近更新 更多