React与Next.js动态路由无法跳转问题求助
Next.js动态路由跳转失败问题修复
问题概述
使用React.js+Next.js开发博客详情页动态路由,创建了blogs文件夹并放置[slug.js]文件,但点击列表页的链接无法跳转到对应详情URL。
现有代码
列表页(Allblog.tsx)链接代码
<Link href={`/blog/${todoList.id}`}>Edit</Link>
详情页(blog/[slug.js])代码
import Axios from "axios"; import {useRouter} from "next/router"; import { Editor } from '@tinymce/tinymce-react'; //import LatestBlogs from "../../components/LatestBlogs/LatestBlogs"; import Link from 'next/link' import { useEffect, useState } from 'react' import Sidebar from '../../components/Sidebar' const slug = ({ posts }) => { return( <div> <h2> Hello World </h2> </div> ); }; export default slug; export const getStaticProps = async ({ params }) => { const { data } = await Axios.get(`https://xxxxxxxxxxxxxx/api/getblogbyuserid/${params.slug}`); const post = data; return { props: { post, }, }; }; export const getStaticPaths = async () => { const { data } = await Axios.get("http://xxxxxxxxxxxxxxxxx/api/blogs"); const posts = data.slice(0, 10); const paths = posts.map((post) => ({ params: { slug: post.id.toString() } })); return { paths, fallback: true, }; };
核心问题与修复方案
1. 路由路径不匹配
你创建的是blogs文件夹,但链接指向的是/blog/${todoList.id},路径前缀不统一。
- 方案一:修改Link路径为
/blogs/${todoList.id},保持和文件夹名称一致:<Link href={`/blogs/${todoList.id}`}>Edit</Link> - 方案二:将
blogs文件夹重命名为blog,匹配现有链接路径。
2. 动态路由文件名错误
动态路由文件必须命名为[slug].js,而非[slug.js]——后者会被Next.js识别为固定文件名,无法触发动态路由解析。直接修改文件名即可。
3. Props传递不匹配
组件接收的参数是{ posts },但getStaticProps返回的是post,导致组件无法获取数据。修正组件参数:
const slug = ({ post }) => { return( <div> <h2> Hello World </h2> </div> ); };
4. API请求协议不一致
getStaticProps使用https协议,getStaticPaths使用http协议,可能引发跨域或请求失败。统一为相同协议(如全用https):
export const getStaticPaths = async () => { const { data } = await Axios.get("https://xxxxxxxxxxxxxxxxx/api/blogs"); // ... 其余代码不变 };
5. Fallback模式加载状态处理(可选)
当fallback: true时,未预渲染的路径会触发增量静态生成,需在组件中添加加载状态提示:
const slug = ({ post }) => { const router = useRouter(); if (router.isFallback) { return <div>加载中...</div>; } return( <div> <h2>{post?.title || '博客详情'}</h2> {/* 渲染博客内容 */} </div> ); };
修正后完整详情页示例
import Axios from "axios"; import { useRouter } from "next/router"; import Link from 'next/link' import { useEffect, useState } from 'react' import Sidebar from '../../components/Sidebar' const SlugPage = ({ post }) => { const router = useRouter(); if (router.isFallback) { return <div>加载中...</div>; } if (!post) { return <div>博客不存在</div>; } return( <div> <h2>{post.title}</h2> <div dangerouslySetInnerHTML={{ __html: post.content }} /> </div> ); }; export default SlugPage; export const getStaticProps = async ({ params }) => { try { const { data } = await Axios.get(`https://xxxxxxxxxxxxxx/api/getblogbyuserid/${params.slug}`); return { props: { post: data, }, revalidate: 60, // 每60秒重新验证生成静态页 }; } catch (error) { return { props: { post: null }, }; } }; export const getStaticPaths = async () => { try { const { data } = await Axios.get("https://xxxxxxxxxxxxxxxxx/api/blogs"); const posts = data.slice(0, 10); const paths = posts.map((post) => ({ params: { slug: post.id.toString() } })); return { paths, fallback: true, }; } catch (error) { return { paths: [], fallback: true, }; } };
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

