reactjs - 即使在签名或登录后也无法访问 protected 路线

标签 reactjs firebase firebase-authentication react-router-dom react-context

我正在制作一个网站,在用户登录后,用户将被重定向到主页。网站的主页和所有其他页面只能由登录用户访问,但即使在用户登录后(firebase auth),网站的其余部分( protected 路由)仍然无法访问,唯一可访问的页面是登录页。我使用的技术是 react、react router dom 和 firebase,这就是我的代码的样子,从 App.js 开始

import Home from "./pages/home/Home";
import Login from "./pages/login/Login";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import List from "./pages/list/List";
import User from "./pages/user/User";
import AddNew from "./pages/addnew/AddNew";
import { useContext } from "react";
import { AuthContext } from "./context/AuthContext";

function App() {
  const {currentUser} = useContext(AuthContext);
  
  const RequireAuth = ({ children }) => {
    return currentUser ? children : <Navigate to="/login" />;
  };


  return (
    <div className="App">
      <BrowserRouter>
        <Routes>
          <Route path="/login" exact element={<Login />} />
          <Route path="/" exact element={ <RequireAuth> <Home /> </RequireAuth> } />
          <Route path="/users" exact element={<RequireAuth><List /></RequireAuth>} />
          <Route path="/users/:id" exact element={<RequireAuth><User /></RequireAuth>} />
          <Route path="/add" exact element={<RequireAuth><AddNew /></RequireAuth>} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;

然后是login.js页面

import React,{useState} from 'react'
import { useContext } from 'react';
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from '../../firebase';
import "./login.css";
import {useNavigate} from "react-router-dom";
import { AuthContext } from '../../context/AuthContext';

export default function Login() {
  const [error, seterror] = useState(false);
  const [email, setemail] = useState("");
  const [password, setpassword] = useState("");
  const navigate = useNavigate();
  const {dispatch} = useContext(AuthContext)
  
  const handleLogin = (e) => {
    e.preventDefault();

    signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        const user = userCredential.user;
        dispatch({type: "LOGIN", payload: user});
        navigate("/");
      })
      .catch((error) => {
        seterror(true);
        console.log(error.message);
      });
  }


  return (
    <div className='login'>
        <form onSubmit={handleLogin}>
          <input className='ok' type="email" placeholder='email' onChange={e => setemail(e.target.value)} />
          <input className='ok' type="password" placeholder='password' onChange={e => setpassword(e.target.value)} />
          <button className='sb'>Submit</button>
          {error && <span className='ks'>Wrong email or password</span>}
        </form>
    </div>
  )
}

然后我有处理状态的 authreducer.js 文件

const AuthReducer = (state, action) => {
    switch (action.type) {
        case "LOGIN": {
            return {
                currentUser: action.payload,
            }
        }
        case "LOGOUT": {
            return {
                currentUser: null
            }
        }
        default:
            return state;
    }
}

export default AuthReducer

最后是 authcontext.js 文件

import { createContext, useEffect, useReducer } from "react";
import AuthReducer from "./AuthReducer";

const INITIAL_STATE = {
    currentUser: JSON.parse(localStorage.getItem("user")) || null,
}

export const AuthContext = createContext(INITIAL_STATE);

export const AuthContextProvider = ({children}) => {
    const [state, dispatch] = useReducer(AuthReducer, INITIAL_STATE);

    useEffect(() => {
        localStorage.setItem("user", JSON.stringify(state.currentUser))
    }, [state.currentUser])

    return (
        <AuthContext.Provider value={{current: state.current, dispatch}}>
            {children}
        </AuthContext.Provider>
    )
}

我不知道是什么导致了这个问题,但我知道它与状态有关,因为在我开始将它与状态结合之前它已经很好地重定向了。可能是什么问题

最佳答案

问题

据我所知,App 没有解构正确的上下文值来处理条件路由保护。

AuthContextProvider 提供具有 currentdispatch 属性的上下文值

<AuthContext.Provider value={{ current: state.current, dispatch }}>
  {children}
</AuthContext.Provider>

但是 App 正在访问一个 currentUser 属性,该属性将是未定义的,因为 state.current 是未定义的。

const { currentUser } = useContext(AuthContext);

const RequireAuth = ({ children }) => {
  return currentUser ? children : <Navigate to="/login" />;
};

Navigate 组件将始终呈现。

解决方案

假设 handleLogin 处理程序正确更新了状态,那么解决方案就是与状态属性保持一致。

<AuthContext.Provider value={{ currentUser: state.currentUser, dispatch }}>
  {children}
</AuthContext.Provider>

...

const { currentUser } = useContext(AuthContext);

const RequireAuth = ({ children }) => {
  return currentUser ? children : <Navigate to="/login" />;
};

关于reactjs - 即使在签名或登录后也无法访问 protected 路线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72225177/

相关文章:

javascript - Jest react 测试 : Check state after delay

ios - iOS 应用程序中的 Firebase 在线状态系统

android - 处理 FirebaseUI 登录和离线 Firestore 数据?

javascript - View 中的 React-360 相机位置

javascript - React.js 是否以不同方式处理 "static"?复合成分

ios - 为什么 Apple Push Notification Authentication Key (Sandbox & Production) 没有出现

android - 在 Android 中初始化或调用 FirebaseAuth.getInstance() 时,Firebase UI 2.0.1 不起作用

firebase - 身份验证注销时出现权限错误 : firebase/ionic/angularfire2

javascript - 返回 React 组件中索引中的第一项

javascript - 有没有办法在 TypeScript 类定义中转义和使用保留字?