【问题标题】:Building context-nested routes with React Router 6使用 React Router 6 构建上下文嵌套路由
【发布时间】:2022-11-22 04:30:34
【问题描述】:

最近我问了一个与同一主题相关的问题,但这次我无意中遇到了另一个问题。按照 Andrew in this post 的指示,我对我的代码进行了一些重构并成功了,但我似乎无法访问 ClientRoutes。

登录和身份验证在两者中都有效,我可以访问 ProRoute,但是当我尝试处理客户端用户时,即使在登录和身份验证检查并检索用户数据之后,我仍停留在登录页面。

所以,我的问题是:构建两个单独的“/home”路由是否可行(如“/home/pro/”和“/home/client”)?相同的路径('/home')适用于两个不同的组件(<HomePro /><HomeClient />),因为有两个上下文(私有/受保护的路由)?我的嵌套路由有问题吗?提前致谢!

这些是我的文件。我正在使用反应路由器 v6。 第一个 App_router(我把 AuthProvider 包装在 App 组件中)

import React from 'react';
import { Route, Routes } from "react-router-dom";

import { ProRoute } from './ProRoute';
import { ClientRoute } from './ClientRoute';

import HomePro from '../Pages/HomePro';
import HomeClient from '../Pages/HomeClient';
import Exercises from '../Pages/Exercises';
import UserForm from '../Pages/Forms/UserForm';
import Login from '../Pages/Login';

const App_Router = () => {
  return (
    <Routes>
      <Route index element={<Login />} />
      <Route path='/login' element={<Login />} />
      <Route path='/register' element={<UserForm />} />
      <Route path='/home'>
        <Route element={<ProRoute />}>
          <Route index element={<HomePro />} />
          <Route path='exercicios' element={<Exercises />} />
        </Route>
        <Route element={<ClientRoute />}>
          <Route index element={<HomeClient />} />
          <Route path='exercicios' element={<Exercises />} />
        </Route>
      </Route>
    </Routes>
  )
}

export default App_Router;

专业路线

import React from 'react'
import { Navigate, Outlet } from 'react-router-dom';
import { useContext } from 'react';
import { AuthContext } from '../Contexts/AuthContext';

export const ProRoute = ({ children }) => {
  const { isAuthenticated, loggedUser, isLoading } = useContext(AuthContext);
  
  if (isLoading) {
    return <section>Carregando...</section>;
  }
  
  if (isAuthenticated && loggedUser.data.type == "Profissional") {
    return children || <Outlet />;
  } else {
    return <Navigate to='/login' replace />;
  }
}

客户端路由

import React from 'react'
import { Navigate, Outlet } from 'react-router-dom';
import { useContext } from 'react';
import { AuthContext } from '../Contexts/AuthContext';

export const ClientRoute = ({ children }) => {
  const { isAuthenticated, loggedUser, isLoading } = useContext(AuthContext);

  if (isLoading) {
    console.log("aqui");
    return <aside>Carregando...</aside>;
  }

  if (isAuthenticated && loggedUser.data.type == "Cliente") {
    return children || <Outlet />;
  } else {
    return <Navigate to='/login' replace />;
  }
}

和登录页面上的 handleLogin 方法

const handleSubmit = async (e) => {
  e.preventDefault();
  await login(values)
    .then( res => {
      setValues({
        email: '',
        senha: '',
        tipoUsuario: ''
      });
      navigate('/home', {replace: true});
    })
    .catch(error => console.log(error));
}

【问题讨论】:

    标签: reactjs authentication react-router react-context


    【解决方案1】:

    这里的问题是代码试图在同一路径上呈现两条路由,但每条路径只能匹配一条路由。

    const App_Router = () => {
      return (
        <Routes>
          <Route index element={<Login />} />
          <Route path='/login' element={<Login />} />
          <Route path='/register' element={<UserForm />} />
          <Route path='/home'>
            <Route element={<ProRoute />}>
              <Route index element={<HomePro />} />    // <-- "/home"
              <Route path='exercicios' element={<Exercises />} />
            </Route>
            <Route element={<ClientRoute />}>
              <Route index element={<HomeClient />} /> // <-- "/home"
              <Route path='exercicios' element={<Exercises />} />
            </Route>
          </Route>
        </Routes>
      );
    }
    

    react-router-dom@6 使用 Route Ranking System 并选择最好的匹配。您将需要区分/消除类似于您暗示的这些路线/路径的歧义。 "/home" 路由渲染 HomeClient"/home" 路由渲染 "HomePro" 屏蔽,无法访问。

    所以,我的问题是:建立两条独立的“/home”路线是可行的 (如“/home/pro/”和“/home/client”)?

    是的,这两条路径足以消除 client 和 pro 路由的歧义。

    const App_Router = () => {
      return (
        <Routes>
          <Route index element={<Login />} />
          <Route path='/login' element={<Login />} />
          <Route path='/register' element={<UserForm />} />
          <Route path='/home'>
            <Route element={<ProRoute />}>
              <Route path="pro" element={<HomePro />} />       // <-- "/home/pro"
              <Route path='exercicios' element={<Exercises />} />
            </Route>
            <Route element={<ClientRoute />}>
              <Route path="client" element={<HomeClient />} /> // <-- "/home/client"
              <Route path='exercicios' element={<Exercises />} />
            </Route>
          </Route>
        </Routes>
      );
    }
    

    如果您不想将 "../pro/.."|"../client/.." 注入 URL 路径,那么另一种方法是稍微重新考虑身份验证。有一个单独的身份验证组件来保护路由,还有一个单独的 pro/client 组件来呈现正确的内容/布局。

    例子:

    export const ProtectedRoute = () => {
      const { isAuthenticated, isLoading } = useContext(AuthContext);
        
      if (isLoading) {
        return <section>Carregando...</section>;
      }
        
      if (isAuthenticated) {
        return <Outlet />;
      } else {
        return <Navigate to='/login' replace />;
      }
    };
    
    export const ProRoute = ({ client, professional }) => {
      const { loggedUser, isLoading } = useContext(AuthContext);
    
      if (isLoading) {
        return <section>Carregando...</section>;
      }
    
      switch(loggedUser.data.type) {
        case "Profissional":
          return professional;
    
        case "Cliente":
          return client;
    
        default:
          return <Navigate to='/login' replace />;
      }
    };
    
    const App_Router = () => {
      return (
        <Routes>
          <Route index element={<Login />} />
          <Route path='/login' element={<Login />} />
          <Route path='/register' element={<UserForm />} />
          <Route element={<ProtectedRoute />}>
            <Route
              path="/home"
            >
              <Route
                index
                element={(
                  <ProClientRoute
                    client={<HomeClient />}
                    professional={<HomePro />}
                  />
                )}
              />
              <Route path='exercicios' element={<Exercises />} />
            </Route>
          </Route>
        </Routes>
      );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 2017-02-03
      相关资源
      最近更新 更多