使用 firebase 进行身份验证检查时未触发本机身份验证提供程序效果

问题描述 投票:0回答:1

我正在为我的应用程序创建一个

register
屏幕,为此,我创建了一个 OnAuth 挂钩,用于注册登录/注册和注销功能,并管理经过身份验证的状态以及用户。

interface authProperties {
  user: {user: any};
  isAuthenticated: boolean;
  register: (
    email: string,
    password: string,
    firstname: string,
    lastname: string,
  ) => Promise<any>;
  login: (email: string, password: string) => Promise<any>;
  logout: () => Promise<any>;
}

export const authContext = createContext<authProperties>({} as authProperties);

export const AuthProvider = ({children}: any) => {
  const [user, setUser] = useState<{user: any}>({user: null});
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, user => {
      console.log('AuthProvider effect triggered', user);
      if (user) {
        setIsAuthenticated(true);
        setUser({user});
      } else {
        setIsAuthenticated(false);
        setUser({user: null});
      }
    });

    return unsubscribe;
  }, []);

const login = async (email: string, password: string) => {
    // login logic
  };
  const register = async (
    email: string,
    password: string,
    firstname: string,
    lastname: string,
  ) => {
    // register logic
  };

  const logout = async () => {
    // logout logic
  }; 

  const value = {
    user,
    isAuthenticated,
    register,
    login,
    logout,
  };

  return <authContext.Provider value={value}>{children}</authContext.Provider>;
};

export const useAuth = () => {
  const value = useContext(authContext);

  if (!value) {
    throw new Error('useAuth must be used within an AuthProvider');
  }

  return value;
};

然后在我的

App.tsx
中,我设置了一个 useEffect 以在 isAuthenticated 更改时触发。

const App = () => {
  // new auth state
  const {isAuthenticated} = useAuth();

  useEffect(() => {
    console.log('App useEffect triggered');
    if (isAuthenticated) {
      console.log('User is authenticated');
    } else {
      console.log('User is not authenticated');
    }
  }, [isAuthenticated]);

  return (
    <AuthProvider>
      {isAuthenticated ? (
        <TabNavigator />
      ) : (
        <SafeAreaProvider>
          <NavigationContainer>
            <Routes />
          </NavigationContainer>
        </SafeAreaProvider>
      )}
    </AuthProvider>
  );
};

export default App;

当我注册新用户时,我的

authprovider
内的效果被正确触发。我在输入和注册时收到日志,我收到正确的 firebase 用户、令牌等。

但是,我预计

isAuthenticated
上的 useEffect 也会被触发。从这里开始,我希望有逻辑转到选项卡导航器(经过身份验证时)或签名/注册(未经身份验证时)

我对原生反应相对较新,不确定为什么没有触发此效果。

如果有人知道,将不胜感激!

reactjs firebase react-native react-hooks
1个回答
0
投票

App
组件正在访问ReactTree中在其上方渲染的some
AuthProvider
组件的上下文,而不是它自身渲染的组件。既然您抱怨或询问为什么不抛出
'useAuth must be used within an AuthProvider'
,我假设有多个
AuthProvider
正在渲染,并且实际上上面有一个
App

每个应用程序可能只需要一个

AuthProvider
组件,因此整个应用程序访问相同的单个提供的上下文值。您可以删除
AuthProvider
渲染的无关
App
组件。

<AuthProvider>
  <App />
</AuthProvider>

使用
useContext
钩子的首选方法。

const App = () => {
  // new auth state
  const { isAuthenticated } = useAuth();

  useEffect(() => {
    console.log('App useEffect triggered');
    if (isAuthenticated) {
      console.log('User is authenticated');
    } else {
      console.log('User is not authenticated');
    }
  }, [isAuthenticated]);

  return isAuthenticated
    ? <TabNavigator />
    : (
      <SafeAreaProvider>
        <NavigationContainer>
          <Routes />
        </NavigationContainer>
      </SafeAreaProvider>
    );
};

export default App;

万一,

AuthProvider
组件
App
渲染,并且实际上存在一些错误,那么要么在ReactTree中将
AuthProvider
移动到比
App
更高的位置,这样
App
可以访问。

使用 Context Consumer 的替代方案

您还可以使用 Context Consumer 有条件地渲染导航器或路线。这仍然假设

AuthProvider
组件在 ReactTree 和
App
中渲染得更高。

示例:

const App = () => {
  return (
    <authContext.Consumer>
      {({ isAuthenticated }) => {
        return isAuthenticated
          ? <TabNavigator />
          : (
            <SafeAreaProvider>
              <NavigationContainer>
                <Routes />
              </NavigationContainer>
            </SafeAreaProvider>
          );
      }}
    </authContext.Consumer>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.