Advanced Features
Stable CSS selectors, custom ID strategies, collision detection, ID pool management, SSR utilities, and custom delimiters.
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.
#my-element
[data-testid="btn"]
[role="nav"]
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.
| Option | Type | Default | Description |
|---|---|---|---|
root | Element | document | Scope uniqueness checks to a subtree |
dataAttributes | string[] | ['data-testid', ...] | Data attributes to check |
maxDepth | number | 5 | Max ancestor levels to traverse |
ignoreIdPattern | RegExp | /^[:.]|^\d/ | Skip dynamic IDs matching this |
ignoreClassPattern | RegExp | - | 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
"btn-1"
"btn-0001"
"ts-17143...-1"
"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.
| Option | Type | Default | Description |
|---|---|---|---|
action | 'warn' | 'throw' | 'skip' | 'warn' | Behavior on collision |
maxSize | number | 100000 | Max 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
| Method | Returns | Description |
|---|---|---|
register(id) | boolean | Register an ID. Returns false on collision |
has(id) | boolean | Check if an ID is registered |
unregister(id) | boolean | Remove an ID from the registry |
clear() | void | Clear all registrations and collision count |
getRegisteredIds() | string[] | Get all registered IDs |
size | number | Number of registered IDs |
collisions | number | Total 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).
| Option | Type | Default | Description |
|---|---|---|---|
prefix | string | "" | Prefix for generated IDs |
suffix | string | "" | Suffix for generated IDs |
autoRefill | boolean | true | Auto-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
| Method | Returns | Description |
|---|---|---|
acquire() | string | Next available ID (reuses released first) |
release(id) | void | Return an ID to the pool |
drain() | void | Clear all available and released IDs |
refill(count) | void | Add more pre-generated IDs |
size | number | Available + released IDs |
totalGenerated | number | Total 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.
| Prop | Type | Default | Description |
|---|---|---|---|
prefix | string | "" | Default prefix for IDs |
suffix | string | "" | Suffix appended to all IDs |
requestId | string | - | 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
});
| Method | Returns | Description |
|---|---|---|
nextId(localPrefix?) | string | Next request-scoped ID |
resetId() | void | Reset counter to 0 |
getCurrentId() | number | Current counter value |
generateDelimitedId(options?): string
Generate an ID with parts joined by a custom delimiter. Empty parts are omitted from the output.
| Option | Type | Default | Description |
|---|---|---|---|
prefix | string | "" | Prefix part |
suffix | string | "" | Suffix part |
delimiter | string | "-" | 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