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

如何使用React Router v6将父组件状态传递给子路由组件?

解决方案:父组件向子路由组件传递状态

针对你的需求,React Router v6+提供了两种直接可行的方式来实现父组件(PageProject)向子路由标签页传递project状态,以下是具体实现:

方式一:使用Outlet的上下文传递(推荐)

这是React Router官方推荐的父子路由状态传递方式,无需额外创建全局Context,适合仅在当前路由层级内传递状态的场景。

1. 调整顶层路由配置(App.tsx)

先在全局路由中明确父路由与子路由的层级关系:

import { createBrowserRouter } from 'react-router-dom';
import { PageProject } from './pages/PageProject';
import { TabA } from './pages/TabA';
import { TabB } from './pages/TabB';
import { TabC } from './pages/TabC';

const router = createBrowserRouter([
  {
    path: '/project/:id',
    element: <PageProject />,
    children: [
      { path: 'a', element: <TabA /> },
      { path: 'b', element: <TabB /> },
      { path: 'c', element: <TabC /> },
      // 可选:访问/project/:id时默认跳转至标签页A
      { index: true, element: <TabA /> },
    ],
  },
]);

2. 在PageProject中传递状态

通过Outlet组件的context属性,将获取到的project状态传递给子路由组件:

import { useState, useEffect } from 'react';
import { Outlet, useParams } from 'react-router-dom';

export function PageProject() {
  const { id } = useParams();
  const [project, setProject] = useState(null);

  useEffect(() => {
    // 模拟API请求获取项目数据
    const fetchProject = async () => {
      if (!id) return;
      const res = await fetch(`/api/projects/${id}`);
      const data = await res.json();
      setProject(data);
    };
    fetchProject();
  }, [id]);

  // 加载状态处理
  if (!project) return <div>加载中...</div>;

  // 传递project状态给子路由
  return <Outlet context={project} />;
}

3. 在子标签页组件中接收状态

使用useOutletContext钩子获取父组件传递的状态:

// TabA.tsx示例
import { useOutletContext } from 'react-router-dom';

// 可根据实际项目类型定义类型,比如:
// interface Project { id: string; name: string; description: string }

export function TabA() {
  const project = useOutletContext();
  
  return (
    <div>
      <h3>标签页A</h3>
      <p>项目名称:{project.name}</p>
      <p>项目描述:{project.description}</p>
    </div>
  );
}

方式二:使用React全局Context

如果项目中多个组件(非仅当前路由层级)需要访问project状态,可通过创建全局Context来管理:

1. 创建ProjectContext

// ProjectContext.ts
import { createContext, useContext } from 'react';

// 定义Context类型,根据实际项目结构调整
export const ProjectContext = createContext<null | { id: string; name: string }>(null);

// 封装自定义钩子简化调用
export function useProject() {
  return useContext(ProjectContext);
}

2. 在PageProject中提供Context

import { useState, useEffect } from 'react';
import { Outlet, useParams } from 'react-router-dom';
import { ProjectContext } from './ProjectContext';

export function PageProject() {
  const { id } = useParams();
  const [project, setProject] = useState(null);

  useEffect(() => {
    const fetchProject = async () => {
      if (!id) return;
      const res = await fetch(`/api/projects/${id}`);
      const data = await res.json();
      setProject(data);
    };
    fetchProject();
  }, [id]);

  if (!project) return <div>加载中...</div>;

  return (
    <ProjectContext.Provider value={project}>
      <Outlet />
    </ProjectContext.Provider>
  );
}

3. 在子标签页组件中使用状态

// TabB.tsx示例
import { useProject } from './ProjectContext';

export function TabB() {
  const project = useProject();
  
  return (
    <div>
      <h3>标签页B</h3>
      <p>项目ID:{project?.id}</p>
    </div>
  );
}

为什么你之前的方式未生效?

React Router的createBrowserRouter是在组件外部定义的静态路由配置,组件内部无法动态添加子路由规则。必须在顶层路由配置中明确父路由与子路由的层级关系,再通过Outlet组件渲染子路由,才能实现状态的传递。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:27:04