这里展示了Reaction-RouterV6中最基本的身份验证实现.PrivateRoutes中的loggedIn标志在更新上下文后更新为真时不会改变,因此当导航到私有路由时不能访问它们.为什么会这样呢?

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;

推荐答案

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 />;
}

Javascript相关问答推荐

从外部访问组件变量-Vueejs

被CSS优先级所迷惑

有没有可能使滑动img动画以更快的速度连续?

Regex结果包含额外的match/group,只带一个返回

用于编辑CSS样式的Java脚本

在使用HighChats时如何避免Datatables重新初始化错误?

IF语句的计算结果与实际情况相反

try 使用javascript隐藏下拉 Select

如何使用JavaScript拆分带空格的单词

TypeError:无法分解';React2.useContext(...)';的属性';basename';,因为它为空

从Nextjs中的 Select 项收集值,但当单击以处理时,未发生任何情况

使用Nuxt Apollo在Piniastore 中获取产品细节

JavaScript不重定向配置的PATH

不同表的条件API端点Reaction-redux

P5JS-绘制不重叠的圆

react 路由DOM有条件地呈现元素

是否设置以JavaScript为背景的画布元素?

如何向内部有文本输入字段的HTML表添加行?

在范围数组中查找公共(包含)范围

Played link-Initialize.js永远显示加载符号