React-router-dom 与路由器外部的组件

问题描述 投票:0回答:1

我正在尝试使用react-router-dom来处理我的React应用程序导航。我在使用标准

useNavigate
函数时遇到了一些问题,因为我的标头组件位于路由器之外。

我正在尝试重组应用程序以将我的标题移动到路由器内,但是当我这样做时,标题不会出现。

目前我的标题呈现在我的index.js 文件中:

    <AppProvider>
      <Header />
      <AppRoutes />
    </AppProvider>

AppRoutes
使用
createBrowserRouter

import React from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

import App from "./App";
import { Header } from "./Header";
import { AppLayout } from "./AppLayout";
import { AccountHome } from "./pages/AccountHome/AccountHome";

const router = createBrowserRouter([
  {
    path: "/",
    element: <AppLayout />,
  },
  { path: "/account", element: <AccountHome /> },
]);

export const AppRoutes = ({ auth }) => {
  return <RouterProvider router={router} />;
};

并且

AppLayout
使用
Outlet
:

export const AppLayout = () => {
  const {
    isAuthenticated,
    isPricingModalOpen,
    pricingOptions,
    setIsPricingModalOpen,
  } = useContext(AppContext);
  return (
    <>
      <PricingModal
        isPricingModalOpen={isPricingModalOpen}
        pricingOptions={pricingOptions}
        setIsPricingModalOpen={setIsPricingModalOpen}
      />
      {isAuthenticated ? <HomePage /> : <LandingPage />}
      <Outlet />
    </>
  );
};

我尝试将标题移动到我的

AppLayout
中,但标题没有出现在
AccountHome

javascript reactjs react-router-dom
1个回答
0
投票

我认为您需要切换到更具可读性和基于组件的结构。 我用这个

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
,它对我来说效果很好。

我正在向您分享我的组件,希望您能理解这个周期。

根文件App.jsx

import 'react-toastify/dist/ReactToastify.css'

**import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'**
import { AuthProvider } from './context/AuthProvider'
import { AdminAuthProvider } from './context/AdminAuthProvider'
import { ToastContainer } from 'react-toastify'
import Signup from './pages/Signup'
import Verification from './pages/Verification'
import Welcome from './pages/Welcome'
import NotFound from './pages/NotFound'
import Login from './pages/Login'
import ProtectedRoute from './ProtectedRoute'
import AdminRoutes from './routes/AdminRoutes'



const App = () => {
    return (
        <AuthProvider>
            <AdminAuthProvider>
            <Router>
                <ToastContainer />
                <Routes>
                    <Route path="*" element={<NotFound />} />
                    <Route path="/" element={<Signup />} />
                    <Route path="/signup" element={<Signup />} />
                    <Route path="/verify" element={<Verification />} />
                    <Route path="/welcome" element={<Welcome />} />
                    <Route path="/login" element={<Login />} />
                    <Route
                        path="/admin/*"
                        element={
                            <ProtectedRoute roles={['admin']}>
                                <AdminRoutes />
                            </ProtectedRoute>
                        }
                    />
                    <Route path="/unauthorized" element={<div>Unauthorized Access</div>} />
                </Routes>
            </Router>
            </AdminAuthProvider>
        </AuthProvider>
    )
}

export default App

在根目录下创建一个目录

/routes
,然后为全局保护路由创建一个组件:
root/routes/ProtectedRoute.jsx
我有这个代码,根据您的用例进行调整

import { Navigate } from 'react-router-dom'
import { useAdminAuth } from '../context/AdminAuthProvider'

const ProtectedRoute = ({ roles, children }) => {
    const { admin } = useAdminAuth();

    if (!admin) {
        return <Navigate to="/login" />;
    }

    if (roles && !roles.includes(admin.role)) {
        return <Navigate to="/unauthorized" />;
    }

    return children;
};

export default ProtectedRoute

如您所见,我只有管理内容需要保护。 因此,在

AdminRoutes.jsx
目录
中创建另一个组件 
/routes

以下是我的代码,您可以根据您的用例调整代码

import { Routes, Route } from 'react-router-dom'
import ProtectedRoute from './ProtectedRoute'
import Dashboard from '../pages/admin/Dashboard'
import Referral from '../pages/admin/Referrals'
import NotFound from '../pages/admin/NotFound'

const AdminRoutes = () => {
    return (
        <ProtectedRoute roles={['admin']}>
            <Routes>
                <Route path="*" element={<NotFound />} />
                <Route path="dashboard" element={<Dashboard />} />
                <Route path="referrals" element={<Referral />} />
            </Routes>
        </ProtectedRoute>
    )
}

export default AdminRoutes

注意上面,我再次定义了路由,同时我也在应用程序的入口文件中定义了它们

App.jsx
。以上路线仅供管理员使用。

您可以忽略任何您不喜欢的额外导入。但我想,这样你就能完成它。

您可以将您的组件单独放置在您需要的所有组件中。

为了解决方案,我正在分享我的

root/pages/admin/dashboard
组件,以便您可以更清楚地看到渲染

import V1 from '../../assets/v1.png'
import V2 from '../../assets/v2.png'

import { useAdminAuth } from "../../context/AdminAuthProvider"
import { Link, useNavigate } from 'react-router-dom';
import { motion } from 'framer-motion';
import { MdLogout } from 'react-icons/md';
import Header from '../../partials/Header';
import Footer from '../../partials/Footer';

import PaginatedItems from '../../components/Pagination';

const Dashboard = () => {

    const { admin, adminLogout } = useAdminAuth();

    const navigate = useNavigate();

    document.title = `YourWebsite | ${admin?.role.charAt(0).toUpperCase() + admin?.role.slice(1) || 'Admin'} | Dashboard`;

    if (!admin) {
        navigate('/login');
    }

    return (
        <>
            <Header />

            <div className="inner-app-container">
                
                <motion.img
                    src={V1}
                    className="left-curve"
                    alt="Left curve decoration"
                />
                <motion.img
                    src={V2}
                    className="bottom-right-shape"
                    alt="Bottom right shape decoration"
                />
                <motion.div 
                    className="inner-app-box"
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    transition={{ duration: 1, ease: "easeIn" }}
                >
                    <div className="inner-app-box-header">
                        <h1>
                            <span>Dashboard <Link className="link" to="/admin/referrals">Referrals</Link></span>
                            <div className="user">
                                Hi! {admin?.name} 
                                <a className="logout-button" onClick={adminLogout}>
                                    <MdLogout size={20} />
                                </a>
                            </div>
                        </h1>
                        <h3>Users raw data</h3>
                    </div>

                    <PaginatedItems itemsPerPage={10} />
                </motion.div>

                <Footer />
            </div>
        </>
    )
}

export default Dashboard

请告诉我这是否对您有帮助,或者您是否需要与此解决方案相关的任何特定内容。

致敬,

© www.soinside.com 2019 - 2024. All rights reserved.