我通过文档在我的应用程序中实现了Firebase身份验证.我有一个登录屏幕和一个登录屏幕,只有当你登录时才能访问.

出于某种原因,当我登录并刷新登录屏幕时,它会将我重定向到登录屏幕,然后再返回到登录屏幕.我费了好大劲才找到原因.

以下是一些可以帮助您解决问题的代码:

index.js(不包括进口和其他方面的东西)

root.render(
  <AuthProvider>
    <Router>
      <Toaster />
      <AppRouter />
    </Router>    
  </AuthProvider>    
);

AuthProvider.js

import React, { useEffect, useState } from "react";
import { onAuthStateChanged } from "firebase/auth";
import { FirebaseAuth } from "./firebase/config";

export const AuthContext = React.createContext();

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);

  useEffect(() => {
    onAuthStateChanged(FirebaseAuth, user => {
      if (user) {
        setCurrentUser(user)
      } else {
        setCurrentUser(null)
      }
    })
  }, []);

  return (
    <AuthContext.Provider value={{ currentUser }}>
      {children}
    </AuthContext.Provider>
  );
};

这是AppRouter.js美元

import { useContext } from "react";
import Landing from "./screens/Landing"
import {
  Navigate,
  BrowserRouter,
  Routes,
  Route
} from "react-router-dom";
import Login from "./screens/auth/Login";
import { AuthContext } from './AuthProvider';

const AppRouter = () => {
  const { currentUser } = useContext(AuthContext);

  return (
    <Routes>
      <Route
        path="/"
        element={!!currentUser ? <Landing /> : <Navigate to="/login" />}
        exact
      />
      <Route
        path="/login"
        element={!currentUser ? <Login /> : <Navigate to="/" />}
        exact
      />
    </Routes>
  )
}

export default AppRouter;

推荐答案

初始currentUser状态与确认的"未认证"用户状态相匹配,例如null.当应用程序挂载时,渲染路由时将使用此初始False值.

使用既不是"已验证"也不是"未验证"的初始currentUser状态值,并对此进行显式判断,并有条件地提前返回,这样应用程序既不会呈现受保护的内容,也不会重定向.

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(); // <-- initially undefined

  useEffect(() => {
    onAuthStateChanged(FirebaseAuth, user => {
      if (user) {
        setCurrentUser(user);
      } else {
        setCurrentUser(null);
      }
    });
  }, []);

  return (
    <AuthContext.Provider value={{ currentUser }}>
      {children}
    </AuthContext.Provider>
  );
};
const AppRouter = () => {
  const { currentUser } = useContext(AuthContext);

  if (currentUser === undefined) {
    return null; // <-- or loading indicator/spinner/etc
  }

  return (
    <Routes>
      <Route
        path="/"
        element={!!currentUser ? <Landing /> : <Navigate to="/login" />}
      />
      <Route
        path="/login"
        element={!currentUser ? <Login /> : <Navigate to="/" />}
      />
    </Routes>
  );
}

有关实施路由保护的更传统方法,请参阅我的答案here.

Reactjs相关问答推荐

在Reaction中更新状态时,我将变得未定义

ReactJs;Reaction-Hook-Form:仅当 Select 了特定 Select 列表选项时才显示文本输入

子路径上未定义useMatches句柄

Reaction路由DOM v6不包含上下文(Supabase)

带有样式的工具提示导致无法向功能组件提供参考警告

点击页脚链接时,如何更改ReactJS导航栏中的活动菜单项(样式为Tailwind CSS)?

有没有比;KeyableShell;组成部分

Next.js `getLayout` 函数没有被调用

ReactJS on AWS Amplify与EC2上的Spring boot服务之间的混合内容错误

React中的功能性组件克隆优化

在react 中单击父级中的按钮时如何将数据从子级发送到父级?

使用 Jest/React 测试库时,如何测试由 setInterval 函数创建的 DOM 更改?

如何从其他组件访问 useQuery refetch 方法?

父状态改变后子组件丢失状态

为什么此代码中的 useState 不更新(文本更新但 id 不更新)?

如何将 id 从页面传递到另一个页面?

React LinkProps 的含义

单击按钮时获取react 表中每一行的属性

React中`onScroll`和`onScrollCapture`之间的区别?

material uireact ,如何从表格中删除阴影?试图找到 api 但找不到正确的属性