示例
react-router-dom 6.30.4: useSearchParams
已验证示例 — npm react-router-dom 6.30.4: useSearchParams. contract 在 node 22 · linux alpine/x64 · docker 上运行并通过: useSearchParams throws an error when invoked…
sha256:af6d5fcc8489a9c202dc927966615ad4980a5577c86c1b4a8f82c9ddc0253382
本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。
提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。
MIT-0
执行证据
声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。
- 证据依据
- 签名契约通过
- 验证回执
- 1
- 构建过它的签名密钥
- 1
声明的环境
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10
验证运行环境
| 环境 | 契约 | 阶段 | 运行日期 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-28 |
案例
HOW- 目标
- verify react-router-dom.useSearchParams in pkg:npm/react-router-dom@6.30.4
- 符号
-
- react-router-dom.useSearchParams
- 环境
- node 22.23.2
- 创建时间
- 2026-08-28T02:14:36Z
契约
- useSearchParams throws an error when invoked outside of a Router context.
- useSearchParams extracts query parameters from URL and returns a URLSearchParams instance.
- useSearchParams retrieves multi-valued query parameters using getAll.
- useSearchParams decodes percent-encoded query parameter keys and values.
- useSearchParams merges defaultInit values when parameters are absent and overrides with URL values.
- useSearchParams operates correctly within data routers created via createMemoryRouter and RouterProvider.
- createSearchParams utility normalizes objects, strings, and key-value arrays into URLSearchParams.
文件
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.js
- test/contract.js
源代码
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify react-router-dom.useSearchParams in pkg:npm/react-router-dom@6.30.4
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/react-router-dom@6.30.4
Demonstrate these symbols/APIs:
- react-router-dom.useSearchParams
Constraints:
- executionContext: node
Required runtime conditions:
- ecosystem: npm
- language: javascript
- moduleSystem: cjs
- packageManager: npm@10.9.8
- runtime: node@22.23.2
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:c0eb82ff3cbddc46f8204ed7da1c4e810ef6688c6ade7ac8c1f1cccb5eadaa61","constraints":{"executionContext":"node"},"contract":["useSearchParams throws an error when invoked outside of a Router context.","useSearchParams extracts query parameters from URL and returns a URLSearchParams instance.","useSearchParams retrieves multi-valued query parameters using getAll.","useSearchParams decodes percent-encoded query parameter keys and values.","useSearchParams merges defaultInit values when parameters are absent and overrides with URL values.","useSearchParams operates correctly within data routers created via createMemoryRouter and RouterProvider.","createSearchParams utility normalizes objects, strings, and key-value arrays into URLSearchParams."],"goal":"verify react-router-dom.useSearchParams in pkg:npm/react-router-dom@6.30.4","kind":"HOW","packages":["pkg:npm/react-router-dom@6.30.4"],"schemaVersion":1,"symbols":["react-router-dom.useSearchParams"]},"contractCommand":["node","test/contract.js"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"cjs","os":"linux","osVersionBucket":"24","packageManager":"npm","packageManagerVersion":"10.9.8","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/react-router-dom@6.30.4"],"schemaVersion":1,"subject":"pkg:npm/react-router-dom@6.30.4","symbols":["react-router-dom.useSearchParams"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample-react-router-dom-use-search-params",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-react-router-dom-use-search-params",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.30.4"
}
},
"node_modules/@remix-run/router": {
"version": "1.23.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz",
"integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"license": "MIT"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.3.1"
}
},
"node_modules/react-router": {
"version": "6.30.4",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz",
"integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.23.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "6.30.4",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz",
"integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.23.3",
"react-router": "6.30.4"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
}
}
}
}
{
"name": "sample-react-router-dom-use-search-params",
"version": "1.0.0",
"private": true,
"license": "MIT-0",
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.30.4"
}
}
{
"schemaVersion": 1,
"goal": "verify react-router-dom.useSearchParams in pkg:npm/react-router-dom@6.30.4",
"kind": "HOW",
"packages": [
"pkg:npm/react-router-dom@6.30.4"
],
"symbols": [
"react-router-dom.useSearchParams"
],
"constraints": {
"executionContext": "node"
},
"runtimeConditions": {
"ecosystem": "npm",
"language": "javascript",
"moduleSystem": "cjs",
"packageManager": "npm@10.9.8",
"runtime": "node@22.23.2"
}
}
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const {
useSearchParams,
createSearchParams,
MemoryRouter,
Routes,
Route,
createMemoryRouter,
RouterProvider,
} = require('react-router-dom');
/**
* Component that calls useSearchParams and passes [searchParams, setSearchParams] to onInspect.
*
* @param {Object} props
* @param {import('react-router-dom').URLSearchParamsInit} [props.defaultInit]
* @param {(params: URLSearchParams, setParams: Function) => void} [props.onInspect]
* @returns {React.ReactElement}
*/
function SearchParamsProbe({ defaultInit, onInspect }) {
const [searchParams, setSearchParams] = useSearchParams(defaultInit);
if (typeof onInspect === 'function') {
onInspect(searchParams, setSearchParams);
}
return React.createElement(
'div',
{ 'data-testid': 'search-params' },
searchParams.toString()
);
}
/**
* Recursively builds Route elements from route configuration definitions.
*
* @param {Array<Object>} routeConfigs
* @returns {React.ReactElement[]}
*/
function buildRouteElements(routeConfigs) {
return routeConfigs.map((cfg, idx) => {
const children = cfg.children ? buildRouteElements(cfg.children) : null;
return React.createElement(
Route,
{
key: cfg.id || idx,
path: cfg.path,
index: cfg.index,
element: cfg.element,
},
children
);
});
}
/**
* Renders route configurations inside a MemoryRouter and returns static markup.
*
* @param {Array<Object>} routeConfigs
* @param {string[]} [initialEntries=['/']]
* @param {number} [initialIndex=0]
* @returns {string} Static HTML markup
*/
function renderWithMemoryRouter(routeConfigs, initialEntries = ['/'], initialIndex = 0) {
const element = React.createElement(
MemoryRouter,
{ initialEntries, initialIndex },
React.createElement(Routes, null, buildRouteElements(routeConfigs))
);
return ReactDOMServer.renderToStaticMarkup(element);
}
/**
* Creates and renders an in-memory data router using createMemoryRouter and RouterProvider.
*
* @param {Array<Object>} routes
* @param {Object} [options]
* @returns {string} Static HTML markup
*/
function renderWithDataRouter(routes, options = {}) {
const router = createMemoryRouter(routes, {
initialEntries: options.initialEntries || ['/'],
initialIndex: options.initialIndex !== undefined ? options.initialIndex : 0,
});
const element = React.createElement(RouterProvider, { router });
return ReactDOMServer.renderToStaticMarkup(element);
}
/**
* Renders a component using useSearchParams outside any Router wrapper.
*
* @param {Object} [props]
* @returns {string} Static HTML markup
*/
function renderWithoutRouter(props = {}) {
const element = React.createElement(SearchParamsProbe, props);
return ReactDOMServer.renderToStaticMarkup(element);
}
module.exports = {
useSearchParams,
createSearchParams,
SearchParamsProbe,
renderWithMemoryRouter,
renderWithDataRouter,
renderWithoutRouter,
};
const assert = require('node:assert/strict');
const React = require('react');
const rrd = require('react-router-dom');
const {
useSearchParams,
createSearchParams,
SearchParamsProbe,
renderWithMemoryRouter,
renderWithDataRouter,
renderWithoutRouter,
} = require('../src/index.js');
// 1. Verify useSearchParams and createSearchParams exports
assert.equal(typeof useSearchParams, 'function', 'useSearchParams must be a function');
assert.strictEqual(useSearchParams, rrd.useSearchParams, 'useSearchParams must match react-router-dom export');
assert.equal(typeof createSearchParams, 'function', 'createSearchParams must be a function');
assert.strictEqual(createSearchParams, rrd.createSearchParams, 'createSearchParams must match react-router-dom export');
// 2. useSearchParams throws an error when invoked outside of a Router context
{
assert.throws(
() => {
renderWithoutRouter();
},
{
name: 'Error',
message: /may be used only in the context of a <Router> component/i,
},
'useSearchParams must throw when used outside a Router context'
);
}
// 3. useSearchParams extracts query parameters from URL and returns a URLSearchParams instance
{
let capturedParams = null;
let capturedSetter = null;
const markup = renderWithMemoryRouter(
[
{
path: '/search',
element: React.createElement(SearchParamsProbe, {
onInspect: (params, setParams) => {
capturedParams = params;
capturedSetter = setParams;
},
}),
},
],
['/search?q=react&sort=desc&page=1']
);
assert.ok(capturedParams instanceof URLSearchParams, 'capturedParams must be an instance of URLSearchParams');
assert.equal(capturedParams.get('q'), 'react', 'param "q" must be "react"');
assert.equal(capturedParams.get('sort'), 'desc', 'param "sort" must be "desc"');
assert.equal(capturedParams.get('page'), '1', 'param "page" must be "1"');
assert.equal(capturedParams.get('missing'), null, 'missing param must return null');
assert.equal(capturedParams.has('q'), true, 'has("q") must be true');
assert.equal(capturedParams.has('missing'), false, 'has("missing") must be false');
assert.equal(typeof capturedSetter, 'function', 'setSearchParams must be a function');
assert.ok(markup.includes('q=react'), 'Markup must contain serialized search params');
}
// 4. useSearchParams retrieves multi-valued query parameters using getAll
{
let capturedParams = null;
renderWithMemoryRouter(
[
{
path: '/filter',
element: React.createElement(SearchParamsProbe, {
onInspect: (params) => {
capturedParams = params;
},
}),
},
],
['/filter?category=books&tag=js&tag=react&tag=router']
);
assert.ok(capturedParams instanceof URLSearchParams, 'capturedParams must be an instance of URLSearchParams');
assert.equal(capturedParams.get('category'), 'books', 'category must be "books"');
assert.deepStrictEqual(
capturedParams.getAll('tag'),
['js', 'react', 'router'],
'getAll("tag") must return all matched tag values in order'
);
}
// 5. useSearchParams decodes percent-encoded query parameter keys and values
{
let capturedParams = null;
renderWithMemoryRouter(
[
{
path: '/query',
element: React.createElement(SearchParamsProbe, {
onInspect: (params) => {
capturedParams = params;
},
}),
},
],
['/query?search%20term=hello%20world%26code&special=%EC%95%88%EB%85%95']
);
assert.ok(capturedParams instanceof URLSearchParams, 'capturedParams must be an instance of URLSearchParams');
assert.equal(capturedParams.get('search term'), 'hello world&code', 'search term must be properly decoded');
assert.equal(capturedParams.get('special'), '안녕', 'UTF-8 encoded value must be properly decoded');
}
// 6. useSearchParams merges defaultInit values when parameters are absent and overrides with URL values
{
let capturedParams = null;
renderWithMemoryRouter(
[
{
path: '/items',
element: React.createElement(SearchParamsProbe, {
defaultInit: { limit: '20', offset: '0', sort: 'created' },
onInspect: (params) => {
capturedParams = params;
},
}),
},
],
['/items?offset=40&filter=active']
);
assert.ok(capturedParams instanceof URLSearchParams, 'capturedParams must be an instance of URLSearchParams');
assert.equal(capturedParams.get('limit'), '20', 'absent parameter "limit" must default to defaultInit value');
assert.equal(capturedParams.get('offset'), '40', 'URL parameter "offset" must override defaultInit value');
assert.equal(capturedParams.get('sort'), 'created', 'absent parameter "sort" must default to defaultInit value');
assert.equal(capturedParams.get('filter'), 'active', 'URL parameter "filter" must be present');
}
// 7. useSearchParams operates correctly within data routers created via createMemoryRouter and RouterProvider
{
let capturedParams = null;
let capturedSetter = null;
const routes = [
{
path: '/explore',
element: React.createElement(SearchParamsProbe, {
onInspect: (params, setParams) => {
capturedParams = params;
capturedSetter = setParams;
},
}),
},
];
const markup = renderWithDataRouter(routes, {
initialEntries: ['/explore?view=grid&theme=dark'],
});
assert.ok(capturedParams instanceof URLSearchParams, 'capturedParams must be an instance of URLSearchParams');
assert.equal(capturedParams.get('view'), 'grid', 'view parameter must be "grid"');
assert.equal(capturedParams.get('theme'), 'dark', 'theme parameter must be "dark"');
assert.equal(typeof capturedSetter, 'function', 'setSearchParams must be a function in data router');
assert.ok(markup.includes('view=grid'), 'Data router markup must include serialized search params');
}
// 8. createSearchParams utility normalizes objects, strings, and key-value arrays into URLSearchParams
{
const fromObject = createSearchParams({ q: 'test', page: '2' });
assert.ok(fromObject instanceof URLSearchParams, 'createSearchParams must return URLSearchParams');
assert.equal(fromObject.toString(), 'q=test&page=2', 'serialized query string must match object');
const fromEntries = createSearchParams([['tag', 'alpha'], ['tag', 'beta']]);
assert.ok(fromEntries instanceof URLSearchParams, 'createSearchParams must return URLSearchParams for array entries');
assert.deepStrictEqual(fromEntries.getAll('tag'), ['alpha', 'beta'], 'multi-value entries must be preserved');
const fromString = createSearchParams('key=val&num=123');
assert.equal(fromString.get('key'), 'val', 'string parsing must work');
assert.equal(fromString.get('num'), '123', 'string parsing must work');
}
console.log('All react-router-dom.useSearchParams contract tests passed successfully.');
原始种子者
匿名