reactjs 如何正确地等待请求完成,防止useEffect Flink ?

pu3pd22g  于 2023-03-17  发布在  React
关注(0)|答案(3)|浏览(124)

所有的auth-wise都工作的很好。我甚至有一个加载状态设置,这样加载器会一直显示直到状态改变,但是我在重新加载的时候还是会出现这种 Flink 。这种 Flink 只发生在Supabase上。我之前用的是Firebase版本,它和我的代码配合得很好。
下面是一段视频供参考:https://imgur.com/a/5hywXj5
编辑:将代码更新为当前版本

export default function Navigation() {
  const { user, setUser } = useContext(AuthenticatedUserContext);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const session = supabase.auth.session();
    setUser(session?.user ?? null);

    const { data: listener } = supabase.auth.onAuthStateChange((_: any, session: any) => {
      setUser(session?.user ?? null);
    });

    setIsLoading(false);
    return () => {
      listener?.unsubscribe();
    };
  }, []);

  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator color={Theme.colors.purple} size="large" />
      </View>
    );
  }

  return (
    <NavigationContainer linking={LinkingConfiguration}>{user ? <AppStack /> : <AuthStack />}</NavigationContainer>
  );
}
tuwxkamq

tuwxkamq1#

好的,自从我第一次问这个问题以来,Supabase已经发布了一些更新。下面是我现在如何在加载应用程序时停止 Flink 。
首先,我们需要为我们的应用程序设置AuthContext。确保用<AuthContextProvider> Package 您的App.tsx
AuthContext.tsx

import React, { createContext, useContext, useEffect, useState } from 'react';

import { Session, User } from '@supabase/supabase-js';

import { supabase } from '../config/supabase';

export const AuthContext = createContext<{ user: User | null; session: Session | null }>({
  user: null,
  session: null,
});

export const AuthContextProvider = (props: any) => {
  const [userSession, setUserSession] = useState<Session | null>(null);
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    supabase.auth.getSession().then(({ data: { session } }) => {
      setUserSession(session);
      setUser(session?.user ?? null);
    });

    const { data: authListener } = supabase.auth.onAuthStateChange(async (event, session) => {
      console.log(`Supabase auth event: ${event}`);
      setUserSession(session);
      setUser(session?.user ?? null);
    });

    return () => {
      authListener.subscription;
    };
  }, []);

  const value = {
    userSession,
    user,
  };
  return <AuthContext.Provider value={value} {...props} />;
};

export const useUser = () => {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useUser must be used within a AuthContextProvider.');
  }
  return context;
};

现在,如果您像我一样使用React Navigation,我们需要检查是否有有效用户将其发送到登录的主屏幕。
Navigation.tsx

export default function Navigation() {
  const { user } = useUser();

  return (
    <NavigationContainer linking={LinkingConfiguration}>
      {user ? <AppStackNavigator /> : <AuthStackNavigator />}
    </NavigationContainer>
  );
}
px9o7tmv

px9o7tmv2#

为其他人重述一下,onAuthStateChange不会在第一次页面加载时执行,因此您使用getUserAuthStatus异步函数触发它。但是session()函数不是异步的,如果没有用户会话,它将立即返回null结果,或者返回已存储在localStorage中的会话。
在这种情况下,getUserAuthStatus的结果将始终返回null,然后onAuthStateChange将触发SIGNED_IN事件和一个会话,该会话将设置用户。
此外,onAuthStateChange函数应该在执行会话步骤之前注册,以便捕获任何触发的事件。在当前表单中,事件可以在session()调用之后但在注册处理程序之前直接触发。
因此,概括渲染步骤如下:

步骤1

isLoading: true
user: null

步骤2

isLoading: false
user: null

步骤3

isLoading false
user: {...}

据我所知,直接使用session而不考虑它是异步的就可以了。

wfsdck30

wfsdck303#

现在React / Next Auth helper提供了不错的帮助,所以你不需要编写自己的useUseruseSessionhttps://supabase.com/docs/guides/auth/auth-helpers

相关问题