Stable CSS Selector Generation

Generate unique, human-readable CSS selectors for any DOM element. The selector generator tries strategies in priority order until it finds a unique match within the given root.

1. Stable ID
#my-element
2. Data attrs
[data-testid="btn"]
3. ARIA role
[role="nav"]
4. Semantic
input[name="email"]

generateSelector(element, options?): string

Generate a unique CSS selector for a DOM element. Falls back to ancestor traversal when no single-element selector is unique.

OptionTypeDefaultDescription
rootElementdocumentScope uniqueness checks to a subtree
dataAttributesstring[]['data-testid', ...]Data attributes to check
maxDepthnumber5Max ancestor levels to traverse
ignoreIdPatternRegExp/^[:.]|^\d/Skip dynamic IDs matching this
ignoreClassPatternRegExp-Exclude matching classes
import { generateSelector } from 'react-unique-id-generator';

const btn = document.querySelector('button.submit');
generateSelector(btn);
// "button.submit" or "#form-container button.submit"

// Skip CSS-in-JS classes
generateSelector(el, {
  ignoreClassPattern: /^css-|^sc-/,
  maxDepth: 3,
});

useStableSelector(ref, options?): string | null

React hook that computes a stable CSS selector for a ref'd element once on mount. Stable across re-renders. Returns null until the ref is attached.

import { useRef } from 'react';
import { useStableSelector } from 'react-unique-id-generator';

function TrackedButton() {
  const ref = useRef<HTMLButtonElement>(null);
  const selector = useStableSelector(ref);

  return (
    <button ref={ref}
      onClick={() => analytics.track('click', { selector })}>
      Click me
    </button>
  );
}

resetSelectorCache(): void

No-op reset function included for API consistency. The selector module is stateless.

IdStrategy Interface

Define how IDs are formatted. Swap strategies without changing component code.

interface IdStrategy {
  generate(prefix: string, suffix: string, counter: number): string;
}

Built-in Strategies

numeric
"btn-1"
zeroPadded(4)
"btn-0001"
timestamp
"ts-17143...-1"
hash
"h-a3f2b1c0"

generateIdWithStrategy(strategy, prefix?, suffix?): string

Generate an ID using a strategy outside of React components.

import { generateIdWithStrategy, numericStrategy,
  zeroPaddedStrategy, hashStrategy } from 'react-unique-id-generator';

generateIdWithStrategy(numericStrategy, 'item-')        // "item-1"
generateIdWithStrategy(zeroPaddedStrategy(4), 'id-')   // "id-0002"
generateIdWithStrategy(hashStrategy, 'h-')              // "h-a3f2b1c0"

useIdWithStrategy(strategy, prefix?, suffix?): string

React hook. Generates a stable ID using the given strategy. Persists across re-renders.

import { useIdWithStrategy, zeroPaddedStrategy } from 'react-unique-id-generator';

function OrderItem() {
  const id = useIdWithStrategy(zeroPaddedStrategy(6), 'order-');
  return <div id={id}>...</div>;
  // <div id="order-000001">
}

Custom Strategy Example

import type { IdStrategy } from 'react-unique-id-generator';

const base36Strategy: IdStrategy = {
  generate(prefix, suffix, counter) {
    return `${prefix}${counter.toString(36)}${suffix}`;
  },
};

generateIdWithStrategy(base36Strategy, 'x-');
// "x-1", "x-2", ... "x-a", "x-b"

CollisionDetector

Track generated IDs and detect duplicates. Useful for debugging, testing, or enforcing uniqueness.

OptionTypeDefaultDescription
action'warn' | 'throw' | 'skip''warn'Behavior on collision
maxSizenumber100000Max registry size before warning
import { CollisionDetector } from 'react-unique-id-generator';

const detector = new CollisionDetector({ action: 'throw' });

detector.register('input-1');  // true
detector.register('input-2');  // true
detector.register('input-1');  // throws Error!

Methods

MethodReturnsDescription
register(id)booleanRegister an ID. Returns false on collision
has(id)booleanCheck if an ID is registered
unregister(id)booleanRemove an ID from the registry
clear()voidClear all registrations and collision count
getRegisteredIds()string[]Get all registered IDs
sizenumberNumber of registered IDs
collisionsnumberTotal collisions detected

checkCollision(id, action?): boolean

Convenience function using a global singleton detector. Returns true if registered, false on collision.

import { checkCollision, resetGlobalCollisionDetector } from 'react-unique-id-generator';

checkCollision('field-1');          // true
checkCollision('field-1', 'skip');  // false (duplicate)
checkCollision('field-1', 'throw'); // throws Error

resetGlobalCollisionDetector();     // reset between tests

IdPool

Generic ID pool with acquire/release semantics. Distinct from AutomationIdPool (which is automation-specific).

OptionTypeDefaultDescription
prefixstring""Prefix for generated IDs
suffixstring""Suffix for generated IDs
autoRefillbooleantrueAuto-generate when exhausted
generator(index) => string-Custom ID generator
import { IdPool } from 'react-unique-id-generator';

const pool = new IdPool(100, { prefix: 'widget-', suffix: '-el' });

const id1 = pool.acquire();  // "widget-1-el"
const id2 = pool.acquire();  // "widget-2-el"

pool.release(id1);           // return to pool
pool.acquire();              // "widget-1-el" (reused)

Methods

MethodReturnsDescription
acquire()stringNext available ID (reuses released first)
release(id)voidReturn an ID to the pool
drain()voidClear all available and released IDs
refill(count)voidAdd more pre-generated IDs
sizenumberAvailable + released IDs
totalGeneratednumberTotal IDs ever generated

Custom Generator

const pool = new IdPool(50, {
  generator: (i) => `session-${Date.now()}-${i}`,
});

useIdPool(size, prefix?): () => string

React hook that pre-generates a pool and returns an acquire function. Stable across re-renders.

import { useIdPool } from 'react-unique-id-generator';

function DynamicList({ items }) {
  const acquireId = useIdPool(20, 'item-');

  return items.map((item) => (
    <li key={acquireId()} id={acquireId()}>
      {item.name}
    </li>
  ));
}

<SSRProvider>

React context provider that scopes IDs per server request. Use requestId to namespace IDs for deterministic, collision-free SSR output.

PropTypeDefaultDescription
prefixstring""Default prefix for IDs
suffixstring""Suffix appended to all IDs
requestIdstring-Request identifier for namespacing
import { SSRProvider, useSSRSafeId } from 'react-unique-id-generator';

function App({ requestId }) {
  return (
    <SSRProvider requestId={requestId} prefix="app-">
      <Form />
    </SSRProvider>
  );
}

function Form() {
  const emailId = useSSRSafeId('email-');  // "email-req123-1"
  const passId = useSSRSafeId('pass-');    // "pass-req123-2"
  return (
    <form>
      <label htmlFor={emailId}>Email</label>
      <input id={emailId} />
    </form>
  );
}

useSSRSafeId(prefix?): string

Hook for SSR-safe IDs inside <SSRProvider>. Falls back to timestamp-based ID outside a provider (with a dev warning). Stable across re-renders.

useSSRContext(): SSRContextValue | null

Access the SSR provider context directly. Returns null outside an <SSRProvider>.

createSSRIdFactory(requestId, prefix?, suffix?)

Non-React factory for server-side ID generation with request scoping. Each factory is fully independent.

import { createSSRIdFactory } from 'react-unique-id-generator';

app.get('*', (req, res) => {
  const ids = createSSRIdFactory(req.id, 'ssr-');

  const headerId  = ids.nextId();  // "ssr-abc123-1"
  const contentId = ids.nextId();  // "ssr-abc123-2"

  ids.resetId();                   // reset for reuse
  ids.getCurrentId();              // 0
});
MethodReturnsDescription
nextId(localPrefix?)stringNext request-scoped ID
resetId()voidReset counter to 0
getCurrentId()numberCurrent counter value

generateDelimitedId(options?): string

Generate an ID with parts joined by a custom delimiter. Empty parts are omitted from the output.

OptionTypeDefaultDescription
prefixstring""Prefix part
suffixstring""Suffix part
delimiterstring"-"Separator between parts
import { generateDelimitedId } from 'react-unique-id-generator';

generateDelimitedId({ prefix: 'app', delimiter: '.' })
// "app.1"

generateDelimitedId({ prefix: 'com', suffix: 'widget', delimiter: '.' })
// "com.2.widget"

generateDelimitedId({ prefix: 'ns', suffix: 'item', delimiter: '::' })
// "ns::3::item"

generateDelimitedId({ prefix: 'path', suffix: 'el', delimiter: '/' })
// "path/4/el"

useDelimitedId(prefix?, delimiter?, suffix?): string

React hook version. Returns a stable delimited ID across re-renders. Works with <IdProvider> context.

import { useDelimitedId } from 'react-unique-id-generator';

function Widget() {
  const id = useDelimitedId('widget', '.', 'container');
  return <div id={id}>...</div>;
  // <div id="widget.1.container">
}

Utilities

resetDelimiterCounter();   // reset to 0
getDelimiterCounter();     // current counter value