React组件跳转并传递Props的实现方案问询
问题
我有一个包含多个独立文件组件的React应用,所有组件嵌套在根组件下,根层级已配置BrowserRouter。现有路由配置如下:
function App() { return ( <div className="app"> <BrowserRouter> <Routes> <Route path="/product" element={<Home />} /> <Route path="/program" element={<Program subject={SubjectSelector.TEST_SUBJECT} program={ProgramSelector.TEST_PROGRAM} />} /> <Route path="/purchase" element={<Purchase />} /> </Routes> </BrowserRouter> </div> ); }
可见,/program路由渲染<Program>组件时传入了固定Props。现在希望点击应用头部导航按钮时,跳转至<Program>组件并传递自定义Props。
我希望避免使用Context(会让不必要的数据在所有组件中可用),已知history.push()、history.location方法,但它们无法直接传递Props;了解location.state,但不想用下面这种冗余方式(通过useLocation提取state后再赋值给Props):
function Program( {subject, program}: {subject: SubjectSelector, program: ProgramSelector} ) { const { state: { sub, prog } = {} } = useLocation(); if( sub != null ) subject = sub; if( prog != null ) program = prog; ... }
期望实现类似如下的效果:
... const goToProgram = (programName: string) => { // 实现渲染带自定义Props的<Program>组件 <Program subject={SubjectSelector.FITNESS} program={programName} /> } return ( <h2 onClick={() => goToProgram(ProgramSelector.SOME_PROGRAM)} >Go To Program</h2> ); ...
解决方案
方案1:路由参数传递(适合可序列化的简单数据)
将需要传递的参数嵌入路由路径,直接通过路由参数映射为组件Props:
- 修改路由配置,定义动态参数:
function App() { return ( <div className="app"> <BrowserRouter> <Routes> <Route path="/product" element={<Home />} /> {/* 定义subject和program为动态路由参数 */} <Route path="/program/:subject/:program" element={<Program />} /> <Route path="/purchase" element={<Purchase />} /> </Routes> </BrowserRouter> </div> ); }
- 导航组件中使用
useNavigate跳转并携带参数:
import { useNavigate } from 'react-router-dom'; // 导航组件内部 const navigate = useNavigate(); const goToProgram = (programName: string) => { navigate(`/program/${SubjectSelector.FITNESS}/${programName}`); }; return ( <h2 onClick={() => goToProgram(ProgramSelector.SOME_PROGRAM)}>Go To Program</h2> );
Program组件通过useParams直接获取参数作为Props:
import { useParams } from 'react-router-dom'; function Program() { const { subject, program } = useParams<{ subject: SubjectSelector; program: ProgramSelector; }>(); // 直接使用subject和program即可 ... }
方案2:封装高阶组件自动映射state到Props
如果不想修改路由路径,依然用location.state传递数据,可以用高阶组件封装Program,自动将state数据注入组件Props,避免组件内的冗余代码:
- 创建高阶组件
withRouterState:
import { useLocation } from 'react-router-dom'; function withRouterState(Component: React.ComponentType<any>) { return (props: any) => { const { state } = useLocation(); // 合并原始Props与state数据,state优先级更高 return <Component {...props} {...state} />; }; }
- 修改路由配置,用高阶组件包裹
Program:
// 导入withRouterState和Program组件 const ProgramWithState = withRouterState(Program); function App() { return ( <div className="app"> <BrowserRouter> <Routes> <Route path="/product" element={<Home />} /> {/* 保留默认Props,state会覆盖默认值 */} <Route path="/program" element={<ProgramWithState subject={SubjectSelector.TEST_SUBJECT} program={ProgramSelector.TEST_PROGRAM} />} /> <Route path="/purchase" element={<Purchase />} /> </Routes> </BrowserRouter> </div> ); }
- 导航组件中通过
navigate传递state:
import { useNavigate } from 'react-router-dom'; const navigate = useNavigate(); const goToProgram = (programName: string) => { navigate('/program', { state: { subject: SubjectSelector.FITNESS, program: programName } }); }; return ( <h2 onClick={() => goToProgram(ProgramSelector.SOME_PROGRAM)}>Go To Program</h2> );
Program组件直接使用Props即可:
function Program( {subject, program}: {subject: SubjectSelector, program: ProgramSelector} ) { // 无需处理state,直接使用传入的Props ... }
内容的提问来源于stack exchange,提问作者Beasted1010
相关产品推荐
相关产品推荐

