LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

搜索页的 URL 状态管理:可分享、可回退、可刷新

zhenglin
2026年10月10日 9:9 本文热度 154

之前做的搜索页被用户吐槽过三件事:搜了关键词、点进结果、按返回——搜索状态没了;想把搜索结果发给同事——没链接可发;刷新页面——回到空白。三个问题的根因是同一个:搜索状态存在组件里,没同步到 URL。这篇记录把搜索页状态搬到 URL 的完整做法。

核心规则:URL 是搜索状态的唯一来源

搜索状态包括:关键词 q、页码 p、市场/语言(hl/gl)、排序、筛选。把它们全部放进 URL,收益立刻兑现:

  • 可分享:复制地址栏就是分享链接

  • 可回退:浏览器前进后退天然工作

  • 可刷新:F5 之后状态还在

  • 可 SSR:服务端能读到参数,直接渲染带结果的首屏(对 SEO 友好)

反过来说,别再用 useState 存一份——两份状态必然不同步。

读取:从 URL 派生状态

"use client";

import { useSearchParams, useRouter, usePathname } from "next/navigation";


function useSearchState() {

  const sp = useSearchParams();

  const router = useRouter();

  const pathname = usePathname();


  // 状态全部从 URL 派生,不做本地副本

  const q = sp.get("q") ?? "";

  const page = Number(sp.get("p") ?? 1);

  const hl = sp.get("hl") ?? "zh-cn";

  const gl = sp.get("gl") ?? "cn";


  const setParams = (

    patch: Record<string, string | number | undefined>,

    mode: "push" | "replace" = "replace",

  ) => {

    const next = new URLSearchParams(sp.toString());

    for (const [k, v] of Object.entries(patch)) {

      if (v === undefined || v === "" || v === null) next.delete(k);

      else next.set(k, String(v));

    }

    const url = `${pathname}?${next.toString()}`;

    mode === "push" ? router.push(url) : router.replace(url);

  };


  return { q, page, hl, gl, setParams };

}

两个关键设计:

  • 默认值不写入 URL:hl=zh-cn、p=1 是默认值就删掉参数,链接短、缓存命中率高

  • replace 和 push 分开:输入过程用 replace,点「搜索」用 push

写回:输入 replace,提交 push

这是最容易搞错的地方。如果每敲一个字都 push 一条历史,返回按钮就废了——用户要按 20 次才退得回去。

function SearchInput({ value, onSubmit }: { value: string; onSubmit: (v: string) => void }) {

  const [text, setText] = useState(value);


  // 输入防抖 + replace:不污染历史

  useEffect(() => {

    const t = setTimeout(() => {

      if (text !== value) onSubmit(text.trim()); // 内部走 setParams(patch, "replace")

    }, 300);

    return () => clearTimeout(t);

  }, [text]);


  return (

    <input

      value={text}

      onChange={(e) => setText(e.target.value)}

      onKeyDown={(e) => e.key === "Enter" && onSubmit(text.trim())}

      placeholder="搜索关键词"

    />

  );

}

配合 router.replace 做草稿态,回车/点按钮时 router.push 落一个「历史锚点」——这样返回按钮退回的是上一次提交的查询,而不是上一个字符。


取数:以 URL 参数为缓存键

状态在 URL 后,数据请求直接以参数为 key,天然享受缓存:

const key = ["/api/serp", q, page, hl, gl];

const { data, isLoading } = useSWR(key, fetcher, { keepPreviousData: true });

  • 返回上一个查询 → key 命中缓存,不重新请求
  • 翻页/切市场 → key 变化,自动请求新数据
  • keepPreviousData 让翻页时旧结果保留,不闪空白

分享与 SEO:两件小事

复制分享:一行搞定。

<button onClick={() => navigator.clipboard.writeText(location.href)}>

  复制结果链接

</button>

服务端首屏:分享链接被爬虫/用户打开时,希望直接看到结果。Next.js App Router 里页面组件能读到 searchParams:

export default async function Page({ searchParams }) {

  const q = searchParams.q as string | undefined;

  const initial = q ? await fetchSerp(q) : null; // 服务端调搜索数据接口

  return <SearchPage q={q} initialData={initial} />;

}

服务端取数这一步,用搜索数据接口(比如 SerpBase 的 /google/search 端点)在服务端发起,Key 天然不暴露给浏览器,首屏直接带结果。


踩坑记录

坑 1:useState + URL 双份状态。 输入框里是 state,URL 里是另一份,改一处忘一处,行为诡异。只留 URL 一份,输入框用本地草稿态 + 防抖回写。

坑 2:每敲一键 push 历史。 返回按钮要按几十次。输入用 replace,提交用 push。

坑 3:忘记 encodeURIComponent。 中文关键词、空格、& 直接拼进 URL 会截断或乱码。用 URLSearchParams 构造,它会正确编码。

坑 4:读取 window.location 导致水合报错。 SSR 首屏没有 window,客户端 hydration 时值不一致。用框架的 useSearchParams(SSR 安全)而不是手读 window.location。

坑 5:默认值全写进 URL。 ?q=x&p=1&hl=zh-cn&gl=cn&sort=relevance——长、丑、缓存全 miss。默认值省略。


工程清单

  1. URL 是搜索状态的唯一来源,不做本地副本

  2. 输入 replace、提交 push,历史干净

  3. 防抖 300ms,别每键请求/写历史

  4. 默认值不写 URL,参数用 URLSearchParams 编码

  5. 取数以 URL 参数为缓存键,返回时命中缓存

  6. 服务端读 searchParams 渲染首屏,分享链接即可用

URL 状态管理这件事,本质上是把「页面当前显示什么」变成「地址栏里写着什么」——前者只对当前用户可见,后者可分享、可回退、可爬取。搜索页尤其适用:搜索结果本来就是「可引用」的内容。

接口参数(q、page、hl/gl 这些)和 URL 参数一一对应,字段说明在 SerpBase 官方文档。你们的搜索页状态存在哪,URL 还是内存?评论区聊聊踩过的坑。


阅读原文:原文链接​


该文章在 2026/10/10 9:09:37 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-9  粤公网安备44030602007207号