如何将Pokedex应用从React Router v5迁移至v6?
React Router v5 迁移到 v6 完整适配指南
1. 入口文件:createBrowserHistory 适配
React Router v6 不再支持手动将 history 实例传入 BrowserRouter,如果不需要自定义路由行为,直接使用内置的 BrowserRouter 即可;如果需要自定义路由配置(比如统一处理错误、嵌套路由),推荐使用 createBrowserRouter + RouterProvider 组合。
v5 旧代码:
import { createBrowserHistory } from 'history'; import { BrowserRouter } from 'react-router-dom'; const history = createBrowserHistory(); ReactDOM.render( <BrowserRouter history={history}> <App /> </BrowserRouter>, document.getElementById('root') );
v6 适配代码:
基础用法(无需自定义history):
import { BrowserRouter } from 'react-router-dom'; ReactDOM.createRoot(document.getElementById('root')).render( <BrowserRouter> <App /> </BrowserRouter> );
自定义路由配置(替代手动history):
import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import App from './App'; import Pokemon from './Pokemon'; const router = createBrowserRouter([ { path: '/', element: <App />, children: [ { path: 'pokemon/:id', element: <Pokemon /> } ] } ]); ReactDOM.createRoot(document.getElementById('root')).render( <RouterProvider router={router} /> );
2. Pokemon组件:替换 match.params 获取路由参数
React Router v6 提供 useParams 钩子直接获取路由参数,无需依赖 match 对象。
v5 旧代码(函数组件+withRouter):
import { withRouter } from 'react-router-dom'; function Pokemon({ match }) { const pokemonId = match.params.id; return <div>当前宝可梦ID:{pokemonId}</div>; } export default withRouter(Pokemon);
v6 适配代码(函数组件直接用useParams):
import { useParams } from 'react-router-dom'; function Pokemon() { const { id } = useParams(); // 解构对应路由定义中的参数名 return <div>当前宝可梦ID:{id}</div>; } export default Pokemon;
如果是类组件,建议优先转为函数组件;若需保留类组件,可自行封装简易版 withRouter 传递参数(参考下一部分)。
3. Pokedex组件:替代 history.push 实现页面跳转
v6 移除了 withRouter,函数组件直接使用 useNavigate 钩子实现跳转;类组件可通过自定义 withRouter 包裹,或转为函数组件。
v5 旧代码(类组件):
import { withRouter } from 'react-router-dom'; class Pokedex extends React.Component { handlePokemonClick = (pokemonId) => { this.props.history.push(`/pokemon/${pokemonId}`); }; render() { return ( <div> <button onClick={() => this.handlePokemonClick(1)}>查看皮卡丘</button> </div> ); } } export default withRouter(Pokedex);
v6 适配方案:
方案1:转为函数组件(推荐)
import { useNavigate } from 'react-router-dom'; function Pokedex() { const navigate = useNavigate(); const handlePokemonClick = (pokemonId) => { navigate(`/pokemon/${pokemonId}`); // 替代history.push // 如需替换当前历史记录:navigate(`/pokemon/${pokemonId}`, { replace: true }) }; return ( <div> <button onClick={() => handlePokemonClick(1)}>查看皮卡丘</button> </div> ); } export default Pokedex;
方案2:自定义withRouter包裹类组件
import { useNavigate, useParams, useLocation } from 'react-router-dom'; import React from 'react'; // 自定义withRouter高阶组件 function withRouter(Component) { return function WrappedComponent(props) { const navigate = useNavigate(); const params = useParams(); const location = useLocation(); return ( <Component {...props} navigate={navigate} params={params} location={location} /> ); }; } // 类组件使用自定义withRouter class Pokedex extends React.Component { handlePokemonClick = (pokemonId) => { this.props.navigate(`/pokemon/${pokemonId}`); // 用navigate替代history.push }; render() { return ( <div> <button onClick={() => this.handlePokemonClick(1)}>查看皮卡丘</button> </div> ); } } export default withRouter(Pokedex);
内容的提问来源于stack exchange,提问作者Fabián Silva
相关产品推荐
相关产品推荐

