如何将React Router参数传递给深层嵌套组件?附Redux示例
解决深层嵌套组件获取路由参数的两种方案
针对你的问题,确实不需要从App开始逐层传递props,这里有两种常用且高效的方案:
方案一:将路由参数同步到Redux Store
如果你的应用需要把路由状态和其他Redux管理的状态联动(比如根据filter触发数据请求),把路由参数存入Redux是个不错的选择:
步骤1:定义处理filter的Action和Reducer
// actions/filterActions.js export const SET_FILTER = 'SET_FILTER'; export const setFilter = (filter) => ({ type: SET_FILTER, payload: filter });
// reducers/filterReducer.js import { SET_FILTER } from '../actions/filterActions'; const initialState = { currentFilter: 'SHOW_ALL' }; export default function filterReducer(state = initialState, action) { switch (action.type) { case SET_FILTER: return { ...state, currentFilter: action.payload || 'SHOW_ALL' }; default: return state; } }
别忘了把这个reducer合并到你的根reducer里。
步骤2:在App组件中同步路由参数到Store
使用React Router的useParams Hook获取路由参数,再通过Redux的useDispatch把参数存入Store:
import { useParams, useEffect } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { setFilter } from './actions/filterActions'; import AddTodo from './AddTodo'; import VisibleTodoList from './VisibleTodoList'; import Footer from './Footer'; const App = () => { const { filter } = useParams(); const dispatch = useDispatch(); // 路由参数变化时更新Store useEffect(() => { dispatch(setFilter(filter)); }, [filter, dispatch]); return ( <div> <AddTodo /> <VisibleTodoList /> {/* 无需再传filter prop */} <Footer /> </div> ); }; export default App;
步骤3:深层组件直接从Store取参数
不管嵌套多少层,只要用useSelector(或connect高阶组件)就能拿到filter:
// 第三层嵌套组件:DeepNestedTodoComponent.js import { useSelector } from 'react-redux'; const DeepNestedTodoComponent = () => { const currentFilter = useSelector(state => state.filter.currentFilter); return ( <div> 当前筛选条件:{currentFilter} </div> ); }; export default DeepNestedTodoComponent;
方案二:直接使用React Router的Hooks(无需Redux)
如果不需要把路由参数存入Redux,React Router v6+提供的useParams Hook可以让任何嵌套在路由树内的组件直接获取路由参数,完全跳过逐层传递props的麻烦:
深层组件直接调用useParams
// 第三层嵌套组件:DeepNestedTodoComponent.js import { useParams } from 'react-router-dom'; const DeepNestedTodoComponent = () => { const { filter } = useParams(); const currentFilter = filter || 'SHOW_ALL'; return ( <div> 当前筛选条件:{currentFilter} </div> ); }; export default DeepNestedTodoComponent;
注意:如果你的项目用的是React Router v5及以下,可以用
withRouter高阶组件包裹深层组件,它会把match、location等路由相关props注入到组件中:import { withRouter } from 'react-router-dom'; const DeepNestedTodoComponent = ({ match: { params } }) => { const currentFilter = params.filter || 'SHOW_ALL'; return <div>当前筛选条件:{currentFilter}</div>; }; export default withRouter(DeepNestedTodoComponent);
方案对比
- 如果需要路由参数和其他Redux状态联动(比如根据filter触发数据请求、更新其他状态),选方案一;
- 如果只是单纯获取路由参数,方案二更轻量直接,不需要额外的Redux代码。
内容的提问来源于stack exchange,提问作者André Herculano
相关产品推荐
相关产品推荐

