You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用createBrowserRouter时SecureRoute包裹的DashboardView无法渲染

React Router SecureRoute 组件渲染问题排查与修复

问题描述

尝试实现SecureRoute组件,并使用createBrowserRouter配置路由,但被SecureRoute包裹的DashboardPresenter的子组件DashboardView无法渲染。相关代码如下:

相关代码

index.js

import SecureRoute from "./utils/SecureRoute";
import SecurityProvider from "./utils/SecurityProvider";
import { createBrowserRouter, RouterProvider} from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <ErrorView />,
  },
  {
    path: "/signup",
    element: <SignUpPresenter />,
    errorElement: <ErrorView />,
  },
  {
    path: "/login",
    element: <LogInPresenter />,
    errorElement: <ErrorView />,
  },
  {
    path: "/dashboard",
    element: (
      <SecureRoute>
        <DashboardPresenter />
      </SecureRoute>
    ),
    errorElement: <ErrorView />,
  },
]);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <SecurityProvider>
        <RouterProvider router={router} />
      </SecurityProvider>
    </Provider>
  </React.StrictMode>
);

SecureRoute.js

import React from "react";
import LogInPresenter from "../presenters/LogInPresenter";
import { Navigate, Outlet } from "react-router-dom";
import useSecurity from "./useSecurity";

const SecureRoute = () => {
  const { loggedIn } = useSecurity();
  return loggedIn ? <Outlet /> : <Navigate to="login" />;
};

export default SecureRoute;

SecurityProvider.js

import { React } from "react";
import SecurityContext from "./SecurityContext";
import { useDispatch, useSelector } from "react-redux";

const SecurityProvider = (props) => {
  const dispatch = useDispatch();
  const {
    data: results,
    error,
    loading,
  } = useSelector((state) => state.user || {});
  return (
    <SecurityContext.Provider
      value={{
        logIn: (email, password) => {
          dispatch({
            type: "LOGIN",
            payload: { email: email, password: password },
          });
        },
        logOut: () => {
          dispatch({ type: "LOGOUT" });
        },
        signUp: (email, password) => {
          dispatch({
            type: "SIGNUP",
            payload: { email: email, password: password },
          });
        },
        loggedIn: results,
        loading: loading,
        error: error,
      }}
    >
      {props.children}
    </SecurityContext.Provider>
  );
};

export default SecurityProvider;

DashboardPresenter.js

import DashboardView from "../views/DashboardView";
import useSecurity from "../utils/useSecurity";

function DashboardPresenter() {
  const { logOut, loggedIn, loading, error } = useSecurity();

  function logOutACB() {
    console.log("Log the user out.");
    logOut();
  }
  return <DashboardView logOut={logOutACB} loading={loading} />;
}

export default DashboardPresenter;

问题原因

  1. SecureRoute 实现与路由用法不匹配:当前SecureRoute使用Outlet组件,Outlet是React Router嵌套路由的占位符,但你是将SecureRoute作为父组件直接包裹DashboardPresenter,这种场景下Outlet无法识别并渲染子组件。
  2. 登录状态判断逻辑有隐患:SecurityProvider中loggedIn直接赋值为results,如果results是空对象或undefined,会导致loggedIn被判断为假,即使登录成功也可能无法正确渲染受保护路由。

修复方案

方案一:修改 SecureRoute 直接渲染子组件

调整SecureRoute接收children属性,适配当前路由配置方式:

// SecureRoute.js
import React from "react";
import { Navigate } from "react-router-dom";
import useSecurity from "./useSecurity";

const SecureRoute = ({ children }) => {
  const { loggedIn } = useSecurity();
  // 转换为布尔值,避免空对象等导致的判断错误
  const isAuthenticated = !!loggedIn;
  return isAuthenticated ? children : <Navigate to="/login" replace />;
};

export default SecureRoute;

方案二:改用嵌套路由结构

如果希望保留Outlet的用法,调整路由配置为嵌套结构:

// index.js
const router = createBrowserRouter([
  // ...其他路由
  {
    element: <SecureRoute />,
    // 所有受保护路由放在children中
    children: [
      {
        path: "/dashboard",
        element: <DashboardPresenter />,
        errorElement: <ErrorView />,
      },
      // 可添加更多受保护路由
    ],
  },
]);

额外优化:修正登录状态判断

在SecurityProvider中确保loggedIn为布尔值,避免非预期的真值判断:

// SecurityProvider.js
value={{
  // ...其他方法
  loggedIn: !!results, // 转换为布尔值,确保登录状态判断准确
  loading: loading,
  error: error,
}}

验证

修改后,登录成功跳转到/dashboard时,SecureRoute会正确渲染DashboardPresenter,进而渲染DashboardView。

内容的提问来源于stack exchange,提问作者saner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 15:25:32