You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

关键修改说明

  1. 干净的基础路径:直接从params中获取区域参数(比如delhi-ncr),和selectedSchools拼接成基础路径,避免重复叠加。
  2. 查询参数管理:使用URLSearchParams来添加/删除参数,自动处理参数编码和重复问题,比手动拼接字符串更可靠。
  3. 防止无限循环:在跳转前对比新路径和当前路径,只有不同时才执行router.push,避免useEffect因路由变化反复触发。

内容的提问来源于stack exchange,提问作者Avnish Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:00:00