mcpField
S
search-params

search-params

github.com/promptfoo开发26.8k66 次安装今天更新
代码仓库

关于 search-params

面向 React 开发者的 URL 搜索参数状态管理指南,介绍如何为页面内状态与可导航步骤选择浏览器历史行为。内容提供经过验证的单参数 Hook、多参数更新和哈希导航模式。

主要功能

  1. 01区分页面内状态与导航步骤
  2. 02使用 Zod 校验单个参数
  3. 03以 replace 更新多个参数
  4. 04为哈希导航选择 push 或 replace
  5. 05保存后规范化 URL

适用场景

  1. 01实现筛选、排序和分页状态
  2. 02在 URL 中保存标签页选择
  3. 03构建支持后退操作的多步向导
  4. 04保存后更新资源 ID

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/promptfoo/promptfoo --skill search-params

安装后在 Claude Code 中输入/search-params确认已加载。

详细介绍

URL 搜索参数状态管理

决策框架

更新 URL(搜索参数或哈希)时,根据变更代表的是页面内状态还是用户可导航的步骤,在 replace 和 push 之间进行选择:

变更类型示例历史记录行为
页面内状态筛选条件、排序、分页、标签页切换、搜索查询replace - 不要污染历史记录
可导航的步骤向导流程、多步骤表单push - 返回按钮应回到上一步
不确定?选择前请询问开发者

为何重要: 将页面内状态变更推入历史记录会使浏览器历史记录变得杂乱。用户点击“返回”时,预期是离开页面,而不是撤销筛选条件的切换。这是导致“返回按钮失效”问题的首要原因。

正确模式

单个搜索参数 - 使用 useSearchParamState(首选)

此 Hook 使用 Zod 进行验证,并且始终在内部使用 replace: true,因此可以自动获得正确的历史记录行为。

import { useSearchParamState } from '@app/hooks/useSearchParamState';
import { z } from 'zod';

const TabSchema = z.enum(['overview', 'details', 'settings']);
const [activeTab, setActiveTab] = useSearchParamState('tab', TabSchema, 'overview');

关键文件: src/app/src/hooks/useSearchParamState.ts

多个搜索参数 - 使用 setSearchParams 并设置 replace: true

一次更新多个参数时,直接使用 setSearchParams,但对于页面内状态,始终传入 { replace: true }:

const [searchParams, setSearchParams] = useSearchParams();

// Updating filters (in-page state -> replace)
setSearchParams(
  (params) => {
    params.set('status', 'active');
    params.set('sort', 'name');
    return params;
  },
  { replace: true },
);
基于哈希的导航 - 使用带 replace 或 push 的 navigate()

对于返回按钮应能在各步骤间切换的向导/多步骤流程,使用 push(默认行为):

// Wizard step navigation - push so back button works between steps
// See: src/app/src/pages/redteam/setup/page.tsx
const updateHash = (newStep: string) => {
  navigate(`#${newStep}`); // push (default) - intentional
};

对于代表页面内状态的哈希变更,使用 replace:

// Tab switch on a detail page - replace to avoid history clutter
navigate(`#${section}`, { replace: true });
保存后的 URL 规范化

如果需要在创建/保存操作后更新 URL 以包含新的 ID(而非用户操作),请使用 replace:

// After first save, update URL to include new ID without adding history entry
navigate(`/evals/${newConfigId}`, { replace: true });

反模式

推入页面内状态变更(会导致返回按钮失效)
// WRONG - every filter change adds a history entry
setSearchParams((params) => {
  params.set('filter', value);
  return params;
});

// WRONG - navigate without replace for state change
navigate(`?tab=${newTab}`);
单个参数未验证就直接使用 useSearchParams
// WRONG - no validation, easy to forget { replace: true }
const [searchParams, setSearchParams] = useSearchParams();
const tab = searchParams.get('tab');
const setTab = (v: string) => {
  setSearchParams((p) => {
    p.set('tab', v);
    return p;
  });
};

// RIGHT - use the hook instead
const [tab, setTab] = useSearchParamState('tab', TabSchema, 'overview');
使用空字符串而不是 null
// WRONG - useSearchParamState will throw an invariant error
setTab('');

// RIGHT - use null to clear a param
setTab(null);

关键文件

  • src/app/src/hooks/useSearchParamState.ts - 主要 Hook(内部使用 replace)
  • src/app/src/pages/eval/components/ResultsView.tsx - 正确使用 { replace: true } 的示例
  • src/app/src/pages/redteam/setup/page.tsx - 在向导步骤中有意使用 push 的示例

评论

支持 Markdown