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

React-Router V7中如何向createBrowserRouter传递props及替代方案咨询

React-Router V7中如何向createBrowserRouter传递props及替代方案咨询

兄弟,你现在的代码确实存在问题哦——你把createBrowserRouter定义在App组件外部,而articles是App内部的useState状态,router初始化的时候根本拿不到这个状态值,就算后续articles更新了,router也不会同步感知到,所以你现在给Home组件传的articles其实是无效的。下面给你几个可行的解决方案,你可以根据自己的场景选择:

方案一:将Router移到App组件内部,用useMemo缓存

把router的创建逻辑放到App组件里,这样就能直接访问到articles状态了,同时用useMemo来缓存router实例,避免每次App渲染都重新创建router,影响性能:

import { useState, useMemo } from 'react';
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';

export function App() {
  const [articles, setArticles] = useState();

  // 用useMemo缓存router,只有当articles变化时才重新创建
  const router = useMemo(() => 
    createBrowserRouter(
      createRoutesFromElements(
        <Route path="/" element={<Layout />}>
          <Route index element={<Home articles={articles} />} />
          <Route path="About" element={<About />} />
        </Route>
      )
    ),
    [articles] // 依赖项数组,articles变化时更新router
  );

  return (
    <div>
      <RouterProvider router={router} />
    </div>
  );
}

这个方案简单直接,不需要额外的状态管理,适合状态只在当前路由树里用到的场景。唯一的小缺点是如果你的路由配置很复杂,放在组件里会让App组件的代码显得有点臃肿。

方案二:使用React Context(你提到的方案)

如果articles是多个组件都需要用到的全局状态,用Context是个不错的选择。具体步骤如下:

步骤1:创建Context

// 可以单独放在一个文件里,比如ArticleContext.js
import { createContext, useContext } from 'react';

const ArticleContext = createContext();

export function ArticleProvider({ children, articles }) {
  return (
    <ArticleContext.Provider value={articles}>
      {children}
    </ArticleContext.Provider>
  );
}

export function useArticles() {
  return useContext(ArticleContext);
}

步骤2:在App里用Provider包裹Router

import { useState } from 'react';
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
import { ArticleProvider } from './ArticleContext';

// router可以继续放在外面,因为不需要直接访问articles了
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<Layout />}>
      <Route index element={<Home />} /> {/* 这里不用传props了 */}
      <Route path="About" element={<About />} />
    </Route>
  )
);

export function App() {
  const [articles, setArticles] = useState();

  return (
    <ArticleProvider articles={articles}>
      <RouterProvider router={router} />
    </ArticleProvider>
  );
}

步骤3:在Home组件里获取数据

import { useArticles } from './ArticleContext';

function Home() {
  const articles = useArticles();
  // 接下来就可以正常使用articles了
  return (
    <div>
      {articles?.map(article => (
        <div key={article.id}>{article.title}</div>
      ))}
    </div>
  );
}

这个方案适合需要在多个组件(比如Layout、其他路由组件)里共享articles的场景,缺点是需要多写一点Context的样板代码,但胜在扩展性强,后续新增需要用articles的组件时,直接用useArticles就能拿数据。

方案三:使用React Router的Loader函数(适合数据从服务端获取的场景)

如果你的articles是从API获取的,或者可以通过路由的loader来提供数据,那可以用React Router的loader功能,Home组件通过useLoaderData来获取数据,完全不需要传props:

步骤1:配置路由的loader

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<Layout />}>
      <Route 
        index 
        element={<Home />} 
        loader={async () => {
          // 这里可以写获取articles的API请求逻辑
          const res = await fetch('/api/articles');
          return res.json();
        }} 
      />
      <Route path="About" element={<About />} />
    </Route>
  )
);

步骤2:在Home组件里获取数据

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

function Home() {
  const articles = useLoaderData();
  return (
    <div>
      {articles.map(article => (
        <div key={article.id}>{article.title}</div>
      ))}
    </div>
  );
}

这个方案符合React Router的设计理念,路由级别的数据由路由自己管理,缺点是如果articles是客户端的本地状态(比如用户在页面上添加/修改的文章),那loader就不太适用了,更适合服务端获取的静态数据。

备注:内容来源于stack exchange,提问作者adam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 10:39:34