Next.js router.push重复路径问题:构造带查询参数的动态路由
问题描述
我想要创建形如http://localhost:3000/boarding-school/delhi-ncr的URL,但使用router.push时不断生成重复路径(如http://localhost:3000/boarding-school/boarding-school/boarding-school/delhi-ncr),最终目标是生成带查询参数的URL(如http://localhost:3000/boarding-school/delhi-ncr?gender=male&somekey=value)。以下是我的代码:
import Layout from "../../../component/Layout/layout"; import { useSearchParams, useRouter, usePathname } from "next/navigation"; import Image from "next/image"; import { useEffect, useState } from "react"; const Listing = ({ params }) => { const router = useRouter(); const pathname = usePathname(); console.log("The Parmas", params); console.log("the router", router); // console.log("pathanme", pathname); // const searchParams = useSearchParams(); // console.log(searchParams); /******** API data **********/ const [instituteData, setInstituteData] = useState([]); const [genderData, setGenderData] = useState([]); const [boardData, setBoardData] = useState([]); const [schoolData, setSchoolData] = useState([]); const [budgetData, setBudgetData] = useState([]); /******************/ /* ************ Filter Data ***********/ const [selectedGender, setSelectedGender] = useState(""); const [selectedBudget, setSelectedBudget] = useState(""); const [selectedBoard, setSelectedBoard] = useState(""); const [selectedSchools, setSelectedSchools] = useState(""); useEffect(() => { let urlSegment = `/${selectedSchools}${pathname}`; if (selectedSchools) { router.push(urlSegment); } if (selectedGender) { // const genderUrl = (urlSegment += `?gender=${selectedGender}`); // router.push(genderUrl); } }, [selectedSchools, selectedGender, router]); const appendSchoolNameToCurrentRoute = (event) => { const { name, value, checked } = event.target; setSelectedSchools(name); };
解决方案
问题根源
你的代码每次触发useEffect时,都会把selectedSchools拼接到当前pathname前面,而pathname已经包含了上一次拼接的内容,导致路径不断重复叠加,最终出现boarding-school/boarding-school/...的错误路径。
修改方案
直接利用路由参数params构建干净的基础路径,并用URLSearchParams管理查询参数,同时避免无限循环:
import Layout from "../../../component/Layout/layout"; import { useSearchParams, useRouter, usePathname } from "next/navigation"; import Image from "next/image"; import { useEffect, useState } from "react"; const Listing = ({ params }) => { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); /******** API data **********/ const [instituteData, setInstituteData] = useState([]); const [genderData, setGenderData] = useState([]); const [boardData, setBoardData] = useState([]); const [schoolData, setSchoolData] = useState([]); const [budgetData, setBudgetData] = useState([]); /******************/ /* ************ Filter Data ***********/ const [selectedGender, setSelectedGender] = useState(""); const [selectedBudget, setSelectedBudget] = useState(""); const [selectedBoard, setSelectedBoard] = useState(""); const [selectedSchools, setSelectedSchools] = useState(""); useEffect(() => { // 用selectedSchools和params里的区域参数构建基础路径 const basePath = selectedSchools ? `/${selectedSchools}/${params.region}` // 假设params里的区域字段是region,按需替换 : pathname; // 基于当前查询参数创建新实例,保留已有参数 const newSearchParams = new URLSearchParams(searchParams); // 更新性别参数 selectedGender ? newSearchParams.set("gender", selectedGender) : newSearchParams.delete("gender"); // 更新预算参数 selectedBudget ? newSearchParams.set("budget", selectedBudget) : newSearchParams.delete("budget"); // 更新学制参数 selectedBoard ? newSearchParams.set("board", selectedBoard) : newSearchParams.delete("board"); // 拼接完整路径 const fullUrl = newSearchParams.size > 0 ? `${basePath}?${newSearchParams.toString()}` : basePath; // 只有路径变化时才跳转,避免无限循环 if (fullUrl !== `${pathname}?${searchParams.toString()}`) { router.push(fullUrl); } }, [selectedSchools, selectedGender, selectedBudget, selectedBoard, params, pathname, searchParams, router]); const appendSchoolNameToCurrentRoute = (event) => { const { name, value, checked } = event.target; setSelectedSchools(name); }; // 组件渲染内容 return ( <Layout> {/* 你的筛选组件和列表内容 */} </Layout> ); }; export default Listing;
关键修改说明
- 干净的基础路径:直接从
params中获取区域参数(比如delhi-ncr),和selectedSchools拼接成基础路径,避免重复叠加。 - 查询参数管理:使用
URLSearchParams来添加/删除参数,自动处理参数编码和重复问题,比手动拼接字符串更可靠。 - 防止无限循环:在跳转前对比新路径和当前路径,只有不同时才执行
router.push,避免useEffect因路由变化反复触发。
内容的提问来源于stack exchange,提问作者Avnish Kumar
相关产品推荐
相关产品推荐

