CodeSampleX

Beispiel

react-router-dom 6.30.4: useParams

Verifiziertes Beispiel für npm react-router-dom 6.30.4: useParams. Der Vertrag lief auf node 22 · linux alpine/x64 · docker und bestand.

sha256:35a258cadebde80755896b02f4bb26dd9b40ebe9003971b5765e66e56a0284f1

Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen. Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen. MIT-0

Ausführungsbelege

Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.

Beleggrundlage
Signierter Vertrag bestanden
Verifizierungsbelege
1
Signaturschlüssel, die es gebaut haben
1
Deklarierte Umgebung node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10

Umgebungen der Verifizierungsläufe

Umgebung Contract Stufen Lauf
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-25

Fall

HOW
Ziel
verify react-router-dom.useParams in pkg:npm/react-router-dom@6.30.4
Pakete
Symbole
  • react-router-dom.useParams
Umgebung
node 22.23.2
Erstellt
2026-08-25T12:37:12Z

Contract

  1. useParams returns an empty object when invoked outside of a Router context.
  2. useParams extracts single named dynamic parameter from the matched route.
  3. useParams extracts and merges parameters across nested route layouts.
  4. useParams decodes percent-encoded URL values in route parameters.
  5. useParams handles optional parameter segments when omitted and when supplied.
  6. useParams captures catch-all wildcard splat parameter via asterisk route.
  7. useParams resolves parameters correctly within data routers created via createMemoryRouter and RouterProvider.

Dateien

  • PROMPT.md
  • csx.json
  • package-lock.json
  • package.json
  • spec.json
  • src/index.js
  • test/contract.js

Quellartefakt herunterladen (tar.gz)

Quelltext

PROMPT.md
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.useParams 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.useParams
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.
csx.json
{"case":{"caseId":"case:sha256:96276875144026a9f83915ba4fed76ebb6a6e83b8b5cfc31fdc07af2175442ee","constraints":{"executionContext":"node"},"contract":["useParams returns an empty object when invoked outside of a Router context.","useParams extracts single named dynamic parameter from the matched route.","useParams extracts and merges parameters across nested route layouts.","useParams decodes percent-encoded URL values in route parameters.","useParams handles optional parameter segments when omitted and when supplied.","useParams captures catch-all wildcard splat parameter via asterisk route.","useParams resolves parameters correctly within data routers created via createMemoryRouter and RouterProvider."],"goal":"verify react-router-dom.useParams 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.useParams"]},"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.useParams"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "sample-react-router-dom-use-params",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "sample-react-router-dom-use-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"
      }
    }
  }
}
package.json
{
  "name": "sample-react-router-dom-use-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"
  }
}
spec.json
{
  "schemaVersion": 1,
  "goal": "verify react-router-dom.useParams in pkg:npm/react-router-dom@6.30.4",
  "kind": "HOW",
  "packages": [
    "pkg:npm/react-router-dom@6.30.4"
  ],
  "symbols": [
    "react-router-dom.useParams"
  ],
  "constraints": {
    "executionContext": "node"
  },
  "runtimeConditions": {
    "ecosystem": "npm",
    "language": "javascript",
    "moduleSystem": "cjs",
    "packageManager": "npm@10.9.8",
    "runtime": "node@22.23.2"
  }
}
src/index.js
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const {
  useParams,
  MemoryRouter,
  Routes,
  Route,
  Outlet,
  createMemoryRouter,
  RouterProvider,
} = require('react-router-dom');

/**
 * Component that calls useParams and passes the returned params object to onInspect callback.
 *
 * @param {Object} props
 * @param {(params: Record<string, string | undefined>) => void} [props.onInspect]
 * @returns {React.ReactElement}
 */
function ParamsProbe({ onInspect }) {
  const params = useParams();
  if (typeof onInspect === 'function') {
    onInspect(params);
  }
  return React.createElement('div', { 'data-testid': 'params' }, JSON.stringify(params));
}

/**
 * Layout component that renders an Outlet for nested routes while capturing params.
 *
 * @param {Object} props
 * @param {(params: Record<string, string | undefined>) => void} [props.onInspect]
 * @returns {React.ReactElement}
 */
function LayoutWithProbe({ onInspect }) {
  const params = useParams();
  if (typeof onInspect === 'function') {
    onInspect(params);
  }
  return React.createElement(
    'div',
    { 'data-layout-params': JSON.stringify(params) },
    React.createElement(Outlet)
  );
}

/**
 * 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 useParams outside any Router wrapper.
 *
 * @param {(params: Record<string, string | undefined>) => void} [onInspect]
 * @returns {string} Static HTML markup
 */
function renderWithoutRouter(onInspect) {
  const element = React.createElement(ParamsProbe, { onInspect });
  return ReactDOMServer.renderToStaticMarkup(element);
}

module.exports = {
  useParams,
  ParamsProbe,
  LayoutWithProbe,
  renderWithMemoryRouter,
  renderWithDataRouter,
  renderWithoutRouter,
};
test/contract.js
const assert = require('node:assert/strict');
const React = require('react');
const rrd = require('react-router-dom');
const {
  useParams,
  ParamsProbe,
  LayoutWithProbe,
  renderWithMemoryRouter,
  renderWithDataRouter,
  renderWithoutRouter,
} = require('../src/index.js');

// 1. Verify useParams export
assert.equal(typeof useParams, 'function', 'useParams must be a function');
assert.strictEqual(useParams, rrd.useParams, 'useParams must match react-router-dom export');

// 2. useParams returns an empty object when invoked outside of a Router context
{
  let inspected = null;
  const markup = renderWithoutRouter((p) => {
    inspected = p;
  });

  assert.ok(markup.includes('{}'), 'Markup outside Router must render empty params object');
  assert.deepStrictEqual(inspected, {}, 'useParams outside Router must return an empty object');
}

// 3. useParams extracts single named dynamic parameter from the matched route
{
  let captured = null;
  const markup = renderWithMemoryRouter(
    [
      {
        path: '/users/:userId',
        element: React.createElement(ParamsProbe, {
          onInspect: (p) => {
            captured = p;
          },
        }),
      },
    ],
    ['/users/usr_42']
  );

  assert.ok(markup.includes('usr_42'), 'Markup must contain user ID');
  assert.deepStrictEqual(captured, { userId: 'usr_42' }, 'captured params must contain userId');
}

// 4. useParams extracts and merges parameters across nested route layouts
{
  let layoutCaptured = null;
  let childCaptured = null;

  const routes = [
    {
      path: '/teams/:teamId',
      element: React.createElement(LayoutWithProbe, {
        onInspect: (p) => {
          layoutCaptured = p;
        },
      }),
      children: [
        {
          path: 'projects/:projectId/tasks/:taskId',
          element: React.createElement(ParamsProbe, {
            onInspect: (p) => {
              childCaptured = p;
            },
          }),
        },
      ],
    },
  ];

  const markup = renderWithMemoryRouter(routes, ['/teams/core-dev/projects/proj-99/tasks/t-1001']);

  assert.ok(markup.includes('core-dev'), 'Markup must contain team ID');
  assert.ok(markup.includes('t-1001'), 'Markup must contain task ID');

  assert.deepStrictEqual(
    layoutCaptured,
    { teamId: 'core-dev', projectId: 'proj-99', taskId: 't-1001' },
    'Layout probe must receive all matched parameters in active branch'
  );
  assert.deepStrictEqual(
    childCaptured,
    { teamId: 'core-dev', projectId: 'proj-99', taskId: 't-1001' },
    'Child probe must receive parent and leaf route parameters'
  );
}

// 5. useParams decodes percent-encoded URL values in route parameters
{
  let captured = null;
  const markup = renderWithMemoryRouter(
    [
      {
        path: '/search/:query',
        element: React.createElement(ParamsProbe, {
          onInspect: (p) => {
            captured = p;
          },
        }),
      },
    ],
    ['/search/hello%20world%2Breact']
  );

  assert.ok(markup.includes('hello world+react'), 'Markup must contain decoded query string');
  assert.deepStrictEqual(
    captured,
    { query: 'hello world+react' },
    'useParams must automatically decode percent-encoded values'
  );
}

// 6. useParams handles optional parameter segments when omitted and when supplied
{
  let capturedWithout = null;
  renderWithMemoryRouter(
    [
      {
        path: '/docs/:version?',
        element: React.createElement(ParamsProbe, {
          onInspect: (p) => {
            capturedWithout = p;
          },
        }),
      },
    ],
    ['/docs']
  );
  assert.deepStrictEqual(
    capturedWithout,
    {},
    'useParams must omit optional parameter or return empty object when omitted'
  );

  let capturedWith = null;
  renderWithMemoryRouter(
    [
      {
        path: '/docs/:version?',
        element: React.createElement(ParamsProbe, {
          onInspect: (p) => {
            capturedWith = p;
          },
        }),
      },
    ],
    ['/docs/v6.30']
  );
  assert.deepStrictEqual(
    capturedWith,
    { version: 'v6.30' },
    'useParams must capture optional parameter when supplied'
  );
}

// 7. useParams captures catch-all wildcard splat parameter via asterisk route
{
  let captured = null;
  const markup = renderWithMemoryRouter(
    [
      {
        path: '/static/*',
        element: React.createElement(ParamsProbe, {
          onInspect: (p) => {
            captured = p;
          },
        }),
      },
    ],
    ['/static/css/themes/dark/main.css']
  );

  assert.ok(markup.includes('css/themes/dark/main.css'), 'Markup must contain wildcard path');
  assert.deepStrictEqual(
    captured,
    { '*': 'css/themes/dark/main.css' },
    'useParams must capture wildcard rest of path under key "*"'
  );
}

// 8. useParams resolves parameters correctly within data routers created via createMemoryRouter and RouterProvider
{
  let captured = null;
  const routes = [
    {
      path: '/catalog/:category/items/:itemId',
      element: React.createElement(ParamsProbe, {
        onInspect: (p) => {
          captured = p;
        },
      }),
    },
  ];

  const markup = renderWithDataRouter(routes, {
    initialEntries: ['/catalog/electronics/items/sku-4567'],
  });

  assert.ok(markup.includes('electronics'), 'Data router markup must include category');
  assert.ok(markup.includes('sku-4567'), 'Data router markup must include itemId');
  assert.deepStrictEqual(
    captured,
    { category: 'electronics', itemId: 'sku-4567' },
    'useParams must extract all parameters in createMemoryRouter configuration'
  );
}

console.log('All react-router-dom.useParams contract tests passed successfully.');

Ursprungs-Seeder

anonym