如何使用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
相关产品推荐
相关产品推荐

