繁体   English   中英

可以在功能组件中声明 react-router v6 路由吗?

[英]Can react-router v6 routes be declared in a functional component?

我有一个只能通过登录访问的应用程序,我尝试以这种方式实现它:

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

import type Admin from '../models/admin';
import {AdminProvider} from './AdminContext';

import LoginC from './components/LoginC';
import RegisterC from './components/RegisterC';
import HomeC from './components/HomeC';

export const Server = () => {
    const [admin, setAdmin] = useState<Admin | undefined>();

    if (!admin) {
        return (
            <Routes>
                <Route path='/' element={<LoginC setAdmin={setAdmin} />} />
                <Route path='/register' element={<RegisterC setAdmin={setAdmin} />} />
            </Routes>
        );
    }

    return (
        <AdminProvider value={admin}>
            <div>Hello server my old friend!</div>
            <HomeC />
        </AdminProvider>
    );
};

export default Server;

LoginC.tsx文件有一个指向注册页面的链接:

<Link to='/register'>Register instead</Link>

我的意图是在用户登录和未登录时返回不同的路由。

但是,当我单击“改为注册”链接时,出现 404(React Router)错误。

它正确地匹配了“/”路由并显示了LoginC组件。

所有路由都需要静态声明吗?

我的意图是根据用户是否设置返回不同的路线。

编辑:

这是创建路由器的代码:

import React from 'react';
import {createRoot} from 'react-dom/client';

import {ThemeProvider} from '@mui/material';

import {
    createBrowserRouter as createRouter,
    RouterProvider,
} from 'react-router-dom';

import theme from './theme';
import Server from './Server';

const router = createRouter([
    {
        path: '/',
        element: <Server />,
    },
]);

const elt = document.getElementById('app');

if (!elt) {
    throw new Error('No element with id "app" found');
}

createRoot(elt).render((
    <React.StrictMode>
        <ThemeProvider theme={theme}>
            <RouterProvider router={router} />
        </ThemeProvider>
    </React.StrictMode>
));

好吧,我不需要在createBrowserRouter中创建路由,而是直接使用BrowserRouter

import React from 'react';
import {createRoot} from 'react-dom/client';

import {ThemeProvider} from '@mui/material';

import {BrowserRouter} from 'react-router-dom';

import theme from './theme';
import Server from './Server';

const elt = document.getElementById('app');

if (!elt) {
    throw new Error('No element with id "app" found');
}

createRoot(elt).render(
    <React.StrictMode>
        <ThemeProvider theme={theme}>
            <BrowserRouter>
                <Server />
            </BrowserRouter>
        </ThemeProvider>
    </React.StrictMode>
);

问题是Server"/"上呈现并试图呈现后代路由。 为了匹配和呈现后代路由,父路由必须将"*"通配符匹配到其路径。 由于路径为"/"而呈现的LoginC组件,但无法匹配"/register"并呈现RegisterC

const router = createRouter([
  {
    path: '/*', // <-- wildcard allows descendent route matching
    element: <Server />,
  },
]);

一种更常见的路由保护模式是使用布局路由和组件来检查保护条件并呈现Outlet组件或重定向到不受保护的路由。

例子:

import { Navigate, Outlet } from 'react-router-dom';

const AdminLayout = ({ admin }) => {
  return admin
    ? (
        <AdminProvider value={admin}>
          <Outlet />
        </AdminProvider>
      )
    : <Navigate to="/login" replace />;
};
export const Server = () => {
  const [admin, setAdmin] = useState<Admin | undefined>();

  return (
    <Routes>
      <Route element={<AdminLayout admin={admin} />}>
        <Route path="/" element={<HomeC />} />
      </Route>
      <Route path='/login' element={<LoginC setAdmin={setAdmin} />} />
      <Route path='/register' element={<RegisterC setAdmin={setAdmin} />} />
    </Routes>
  );
};

由于没有出现任何 RRDv6.4 数据 API 被使用,只需将Server呈现为路由器即可。

import { BrowserRouter } from 'react-router-dom';

createRoot(elt).render((
  <React.StrictMode>
    <ThemeProvider theme={theme}>
      <BrowserRouter>
        <Server />
      </BrowserRouter>
    </ThemeProvider>
  </React.StrictMode>
));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM