react-router-dom v6跳转详情页报读取undefined的params属性TypeError
问题描述
使用ReactJS、react-router-dom v6、Axios对接https://restcountries.com/v2/all接口开发国家信息展示项目时,HomePage首页可正常渲染,页面加载时通过axios拉取国家数据、遍历生成Card卡片列表,点击卡片可触发路由跳转行为,但跳转后页面抛出Uncaught TypeError: Cannot read properties of undefined (reading 'params')报错。
相关代码
1. HomePage首页组件
import React from 'react'; import axios from 'axios'; import { useState, useEffect } from 'react'; import { useNavigate,useParams } from 'react-router-dom'; import { Main } from '../components/Main'; import { Controls } from '../components/Controls'; import { ALL_COUNTRIES } from '../config'; import { List } from '../components/List'; import { Card } from '../components/Card'; import { Details } from './Details'; export const HomePage = () => { const [countries,setCountries] = useState([]); const navigate = useNavigate(); useEffect(() => { axios.get(ALL_COUNTRIES).then(({data})=>setCountries(data)) },[]); return ( <> <Controls/> <List> { countries.map((c) => { const countryInfo = { img: c.flags.png, name: c.name, info: [ { title:'Population', description:c.population.toLocaleString(), }, { title:'Region', description:c.region, }, { title:'Flag', description:c.capital, }, ], }; return ( <Card key={c.name} onClick={(e) => { navigate('/country/${c.name}'); }} {...countryInfo} /> ) }) } </List> </> ); };
2. Details详情页组件
import React from 'react'; import { useParams } from 'react-router-dom'; export const Details = ({match,params}) => { const { name } = useParams(); return ( <div> Details {match.params.name} </div> ); };
3. config.js接口配置
const BASE_URL = 'https://restcountries.com/v2/'; export const ALL_COUNTRIES=BASE_URL+"all?fields=name,flags,population,capital,region"; export const searchByContry=(name)=>BASE_URL+'name/'+name; export const filterByCode=(code)=>BASE_URL+'alpha?code'+code.join('');
4. App.jsx根组件路由配置
import React from 'react'; import ReactDOM from 'react-dom'; import axios from 'axios'; import { Route,Routes,Router,useParams} from 'react-router-dom'; import {useState, useEffect} from 'react'; import './App.css'; import styled from 'styled-components'; import Header from './components/Header'; import { Main } from './components/Main'; import {NotFound} from './pages/NotFound'; import { HomePage } from './pages/HomePage'; import { Details } from './pages/Details'; function App() { return ( <> <Header/> <Main> <Routes> <Route path="/" element={<HomePage/>}/> <Route path="country/:name" element={<Details/>}/> <Route path="*" element={<NotFound/>}/> </Routes> </Main> </> ); } export default App;
报错原因
- 核心触发原因:react-router-dom v6版本完全移除了v5版本中默认向路由组件注入的
match/location/history路由props,Details组件中解构的match实际为undefined,后续读取match.params.name时就会触发类型错误。 - 隐藏逻辑bug:HomePage中跳转路由使用单引号包裹模板字符串,
'/country/${c.name}'不会解析内部的c.name变量,最终跳转路径为字面量/country/${c.name},即使修复params报错也无法获取正确的国家名称参数。 - 潜在接口问题:config.js中
filterByCode方法的接口拼接存在语法错误,缺少参数等号且参数名不符合接口规范,后续调用该接口时会直接请求失败。
修复方案
- 修正Details组件逻辑,删除旧版本路由props相关代码,直接使用
useParams钩子获取路由参数,修改后代码如下:
import React from 'react'; import { useParams } from 'react-router-dom'; export const Details = () => { const { name } = useParams(); return ( <div> Details {name} </div> ); };
- 修正HomePage的路由跳转写法,将单引号替换为反引号,让模板字符串正常解析变量:
onClick={(e) => { navigate(`/country/${c.name}`); }}
- (可选优化)修正config.js中接口拼接错误,适配restcountries v2接口规范:
export const filterByCode=(code)=>BASE_URL+`alpha?codes=${code.join(',')}`;
注:restcountries v2多国家编码查询的参数名为
codes,多个编码之间用英文逗号分隔,原写法缺少参数等号且参数名错误,会导致后续筛选功能异常。
内容的提问来源于stack exchange,提问作者Michael Hamar
相关产品推荐
相关产品推荐

