React单篇文章访问异常:路由未匹配位置"/posts/1"求助
解决React Router路由匹配错误:No routes matched location "/posts/1"
问题描述
我想要为博客网站实现单篇文章阅读页面,但无法正常访问,访问时提示「No routes matched location "/posts/1"」。以下是项目相关代码:
App.js
import Demo from "./components/Pages/Demo/Demo"; import DemoPost from "./components/Pages/Demo/Post"; function App() { return ( <div> <Routes> <Route path='/posts' exact element={<Demo />} /> <Route path='/demo/:pid' element={<DemoPost />} /> </Routes> </div> ); } export default App;
Demo组件(Posts.js)
import React, { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; function Demo() { const [posts, setPosts] = useState([]); useEffect(() => { fetch('https://jsonplaceholder.typicode.com/posts') .then(response => response.json()) .then(json => setPosts(json)) }, []); return ( <div className="posts"> <div className="grid"> {posts.map(post => ( <div key={post.id}> <Link to={`/posts/${post.id}`}> <h2>{post.title}</h2> <p>{post.body}</p> </Link> </div> ))} </div> </div> ) } export default Demo
Post.js
import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; function Post({ match }) { const [post, setPost] = useState([]); useEffect(() => { fetch(`https://jsonplaceholder.typicode.com/posts${match.params.pid}`) .then(response => response.json()) .then(json => setPost(json)) console.log(match, 'why not show match'); }, []); return ( <div className="posts"> <div className="post-container"> <h1>{post.title}</h1> <p>{post.body}</p> </div> </div> ) } export default Post
问题分析与修复方案
1. 核心问题:路由路径不匹配
Demo组件生成的文章链接是/posts/${post.id},但App.js中配置的单篇文章路由是/demo/:pid,两者路径完全不对应,直接导致路由匹配失败。
修复方法:修改App.js中的路由路径,和链接保持一致:
<Route path='/posts/:pid' element={<DemoPost />} />
2. 参数获取与请求URL错误
Post组件中导入了useParams但未使用,反而依赖已被React Router v6废弃的match props,导致match为undefined,进而生成错误的请求URL(缺少斜杠,变成posts1这类无效地址)。
修复方法:
- 移除
{ match }props,改用useParams获取pid参数 - 修正fetch的URL,补上前斜杠
/ - 初始状态改为空对象(单篇文章是对象而非数组)
- 将pid加入useEffect依赖数组,确保参数变化时重新请求
修改后的Post.js:
import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; function Post() { const { pid } = useParams(); const [post, setPost] = useState({}); useEffect(() => { fetch(`https://jsonplaceholder.typicode.com/posts/${pid}`) .then(response => response.json()) .then(json => setPost(json)) }, [pid]); return ( <div className="posts"> <div className="post-container"> <h1>{post.title}</h1> <p>{post.body}</p> </div> </div> ) } export default Post
3. 可选优化:嵌套路由(按需使用)
如果希望列表页和详情页保持布局嵌套关系,可以改用嵌套路由写法:
修改App.js:
import Demo from "./components/Pages/Demo/Demo"; import DemoPost from "./components/Pages/Demo/Post"; import { Outlet } from 'react-router-dom'; function App() { return ( <div> <Routes> <Route path='/posts' element={<Demo />}> <Route path=':pid' element={<DemoPost />} /> </Route> </Routes> </div> ); } export default App;
同时在Demo组件中添加<Outlet />用于渲染子路由内容,这样详情页会在列表页的布局框架内展示。
内容的提问来源于stack exchange,提问作者Md Yousuf
相关产品推荐
相关产品推荐

