StreamEdit组件props为空,无法获取match.params.id的问题
问题:React Router v6 类组件无法获取路由参数 match.params.id
我在App.js中配置了带参数的路由/streams/edit/:id,但StreamEdit类组件里拿不到this.props.match.params.id,打印props发现是空的,期望能正常获取路由ID。
App.js 代码:
import { Route, Routes } from 'react-router-dom'; import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom"; import './App.css'; //,BrowserRouter as Router const App = () => { return ( <div id='app_div'> <HistoryRouter history={history}> <Header /> <Routes> <Route path='/' exact Component={StreamList} /> <Route path='/streams/new' Component={StreamCreate} /> <Route path='/streams/edit/:id' Component={StreamEdit} /> <Route path='/streams/delete' Component={StreamDelete} /> <Route path='/streams/show' Component={StreamShow} /> </Routes> </HistoryRouter> </div> ); }; export default App;
StreamEdit 组件代码:
import React from "react"; import { connect } from "react-redux"; import { fetchStream } from '../../actions'; class StreamEdit extends React.Component{ componentDidMount() { this.props.fetchStream(this.props.match.params.id); } } const mapStateToProps = (state, ownProps) => { console.log(ownProps) return { stream: state.streams }; } export default connect(mapStateToProps, { fetchStream })(StreamEdit);
原因
React Router v6 完全移除了自动向组件注入match、location、history这些路由props的机制,不管你用Component还是element属性渲染组件,都不会拿到这些旧版的路由props。
解决办法
1. 给类组件套一个自定义的withRouter高阶组件
v6官方不再提供withRouter,但可以自己封装一个:
// 新建withRouter.js import { useParams, useLocation, useNavigate } from 'react-router-dom'; export default function withRouter(Component) { return function WrappedComponent(props) { const params = useParams(); const location = useLocation(); const navigate = useNavigate(); return <Component {...props} params={params} location={location} navigate={navigate} />; }; }
然后修改StreamEdit的导出:
import withRouter from './withRouter'; // 导入你封装的文件 // ...其他代码不变 export default withRouter(connect(mapStateToProps, { fetchStream })(StreamEdit));
之后在组件里用this.props.params.id替代原来的this.props.match.params.id:
componentDidMount() { this.props.fetchStream(this.props.params.id); }
2. 把类组件改成函数组件(推荐)
v6更适配函数组件,用useParams钩子直接拿参数:
import React, { useEffect } from "react"; import { connect } from "react-redux"; import { fetchStream } from '../../actions'; import { useParams } from 'react-router-dom'; const StreamEdit = (props) => { const { id } = useParams(); useEffect(() => { props.fetchStream(id); }, [id, props.fetchStream]); // 这里写原来的组件逻辑,比如渲染内容 return <div>编辑流: {id}</div>; }; const mapStateToProps = (state) => { return { stream: state.streams }; }; export default connect(mapStateToProps, { fetchStream })(StreamEdit);
3. 直接在Route的element里传递参数(不推荐)
如果非要保留类组件,也可以在App.js的Route里用element属性手动传,但本质还是要结合钩子:
// App.js里修改Route <Route path='/streams/edit/:id' element={<StreamEdit />} />
但这种方式还是得用上面的withRouter或者把组件改成函数组件才能拿到id,所以不如直接用前两种方法。
内容的提问来源于stack exchange,提问作者saba
相关产品推荐
相关产品推荐

