Пример
react-router-dom 6.30.4: useSearchParams
Проверенный пример — npm react-router-dom 6.30.4: useSearchParams. Контракт выполнен на node 22 · linux alpine/x64 · docker и пройден.
sha256:af6d5fcc8489a9c202dc927966615ad4980a5577c86c1b4a8f82c9ddc0253382
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
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.');
Исходный сидер
аноним