reactjs React Router保护的路由 Package 器无法检测到来自AuthProvider的新身份验证状态

zpgglvta  于 2023-10-17  发布在  React
关注(0)|答案(2)|浏览(121)

这里展示了React-Router v6中最基本的身份验证实现。PrivateRoutes中的loggedIn标志在更新上下文后更新为true时不会改变,因此在导航到它们时无法访问私有路由。为什么会这样?

import './App.css';
import {
  BrowserRouter,
  Navigate,
  Outlet,
  Route,
  Routes,
  useNavigate
} from 'react-router-dom';
import React, { useState } from 'react';

function App() {
  return (
    <div>
      <AuthProvider>
        <BrowserRouter>
          <Routes>
            <Route path="/" element={<HomePage />} />

            <Route element={<PrivateRoutes />}>
              <Route path="/secret" element={<SecretPage />} />
              {/** ... Other protected pages ...*/}
            </Route>
            
          </Routes>
        </BrowserRouter>
      </AuthProvider>
    </div>
  );
}

function PrivateRoutes() {
  const { loggedIn } = useAuth();

  return loggedIn ? <Outlet />: <Navigate to="/" />
}

function HomePage() {
  const navigate = useNavigate();

  return <>
    <h1>Home page</h1>
    <button onClick={() => navigate('/secret')}>
      Go to secret page
    </button>
  </>
}

function SecretPage() {
  return <>
    <h1>Secret Page</h1>
  </>
}

const AuthContext = React.createContext()

const AuthProvider = ({ children }) => {
  const { loggedIn, signIn } = useAuth()

  return
    <AuthContext.Provider value={loggedIn}>
      
      {/** 
       * Button to trigger sign in and showing the
       * current status.
      */}
      <button onClick={signIn}>LogIn</button>
      <h2>Logged In: {loggedIn.toString()}</h2>
      <p>-----------------------</p>

      {children}
    </AuthContext.Provider>
}

const useAuth = () => {
  const [loggedIn, setLoggedIn] = useState(false)

  const signIn = () => {

    {/** sign in logic ....*/}

    setLoggedIn(true);
  };

  return { loggedIn, signIn };
}

export default App;
jaxagkaj

jaxagkaj1#

useAuth是一个React钩子,React钩子不共享内部状态。useAuth的每个示例都有自己独立的loggedIn状态。
重构AuthProvider以保持loggedIn状态,并更新useAuth钩子以使用提供的上下文值。这就是所有useAuth示例都获得相同值的方式。

const AuthContext = React.createContext();

const AuthProvider = ({ children }) => {
  const [loggedIn, setLoggedIn] = useState();

  const signIn = () => {
    {/** sign in logic ....*/}
    setLoggedIn(true);
  };

  return (
    <AuthContext.Provider value={{ loggedIn, signIn }}>
      {/** 
       * Button to trigger sign in and showing the
       * current status.
      */}
      <button onClick={signIn}>LogIn</button>
      <h2>Logged In: {loggedIn.toString()}</h2>
      <p>-----------------------</p>

      {children}
    </AuthContext.Provider>
  );
}

const useAuth = () => React.useContext(AuthContext);
function PrivateRoutes() {
  const { loggedIn } = useAuth();

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

  return loggedIn
    ? <Outlet />
    : <Navigate to="/" replace />;
}
sh7euo9m

sh7euo9m2#

试试这个

import { useLocation, Navigate, Outlet } from "react-router-dom";
function PrivateRoutes(){
  const {loggedIn} = useAuth();
  return loggedIn ? <Outlet/>: <Navigate to="/" state={{from:location}} replace/>

}

相关问题