Hooks
No hooks found in any category.
useSymbol
utilityInstallation
npx usehooks-cli@latest add use-symbol
Description
A React hook that provides utilities for creating and managing JavaScript Symbols. Symbols are primitive values that are guaranteed to be unique and are often used as unique property keys that won't collide with other code. This hook offers symbol creation, global registry management, and access to well-known symbols.
Return Type
UseSymbolReturn
Property | Type | Description |
---|---|---|
createSymbol | (description?: string) => symbol | Creates a new unique symbol with optional description |
getGlobalSymbol | (key: string) => symbol | Gets or creates a symbol from the global symbol registry |
getSymbolKey | (symbol: symbol) => string | undefined | Gets the key for a symbol in the global registry |
isSymbol | (value: any) => value is symbol | Type guard to check if a value is a symbol |
getDescription | (symbol: symbol) => string | undefined | Gets the description of a symbol |
wellKnownSymbols | object | Object containing all well-known symbols (iterator, hasInstance, etc.) |
symbols | symbol[] | Array of symbols created or managed by this hook |
addSymbol | (symbol: symbol) => void | Adds an existing symbol to the managed collection |
removeSymbol | (symbol: symbol) => void | Removes a symbol from the managed collection |
clearSymbols | () => void | Clears all symbols from the managed collection |
Examples
Creating Unique Property Keys
Use symbols as unique property keys that won't collide
1const { createSymbol } = useSymbol();
2
3const privateKey = createSymbol('private');
4const obj = {
5 publicProp: 'visible',
6 [privateKey]: 'hidden'
7};
8
9// privateKey is unique and won't conflict with other properties
Global Symbol Registry
Share symbols across different parts of your application
1const { getGlobalSymbol, getSymbolKey } = useSymbol();
2
3const sharedSymbol = getGlobalSymbol('app.config');
4const key = getSymbolKey(sharedSymbol); // 'app.config'
5
6// Same symbol can be retrieved elsewhere with getGlobalSymbol('app.config')
Well-Known Symbols
Access built-in JavaScript symbols for custom behavior
1const { wellKnownSymbols } = useSymbol();
2
3const customIterable = {
4 [wellKnownSymbols.iterator]: function* () {
5 yield 1;
6 yield 2;
7 yield 3;
8 }
9};
10
11// Now customIterable can be used with for...of loops
Symbol Management
Track and manage symbols in your component
1const { symbols, createSymbol, removeSymbol, clearSymbols } = useSymbol();
2
3const handleCreateKey = () => {
4 const newKey = createSymbol('dynamic-key');
5 console.log(`Created symbol, total: ${symbols.length}`);
6};
7
8const handleClear = () => {
9 clearSymbols();
10 console.log('All symbols cleared');
11};
Type Checking and Utilities
Utility functions for working with symbols
1const { isSymbol, getDescription, createSymbol } = useSymbol();
2
3const mySymbol = createSymbol('test symbol');
4
5if (isSymbol(mySymbol)) {
6 const desc = getDescription(mySymbol); // 'test symbol'
7 console.log(`Symbol description: ${desc}`);
8}
Dependencies
react
Notes
- •Symbols created with createSymbol() are guaranteed to be unique
- •Global symbols created with getGlobalSymbol() can be shared across the application
- •Well-known symbols enable customization of built-in JavaScript operations
- •The hook maintains a collection of symbols for easy management and cleanup
- •Symbols are garbage collectable and can be used as WeakMap keys
- •Each Symbol() call creates a completely unique value, even with the same description
Implementation
1"use client";
2
3import { useState, useCallback, useMemo, useRef } from "react";
4
5interface UseSymbolReturn {
6 // Create new unique symbols
7 createSymbol: (description?: string) => symbol;
8
9 // Global symbol registry operations
10 getGlobalSymbol: (key: string) => symbol;
11 getSymbolKey: (symbol: symbol) => string | undefined;
12
13 // Symbol utilities
14 isSymbol: (value: any) => value is symbol;
15 getDescription: (symbol: symbol) => string | undefined;
16
17 // Well-known symbols
18 wellKnownSymbols: {
19 iterator: symbol;
20 asyncIterator: symbol;
21 hasInstance: symbol;
22 isConcatSpreadable: symbol;
23 species: symbol;
24 toPrimitive: symbol;
25 toStringTag: symbol;
26 unscopables: symbol;
27 match: symbol;
28 matchAll: symbol;
29 replace: symbol;
30 search: symbol;
31 split: symbol;
32 };
33
34 // Symbol collection management
35 symbols: symbol[];
36 addSymbol: (symbol: symbol) => void;
37 removeSymbol: (symbol: symbol) => void;
38 clearSymbols: () => void;
39}
40
41export function useSymbol(): UseSymbolReturn {
42 const [symbols, setSymbols] = useState<symbol[]>([]);
43 const symbolsRef = useRef<Set<symbol>>(new Set());
44
45 const createSymbol = useCallback((description?: string): symbol => {
46 const newSymbol = Symbol(description);
47 setSymbols((prev) => [...prev, newSymbol]);
48 symbolsRef.current.add(newSymbol);
49 return newSymbol;
50 }, []);
51
52 const getGlobalSymbol = useCallback((key: string): symbol => {
53 return Symbol.for(key);
54 }, []);
55
56 const getSymbolKey = useCallback((symbol: symbol): string | undefined => {
57 return Symbol.keyFor(symbol);
58 }, []);
59
60 const isSymbol = useCallback((value: any): value is symbol => {
61 return typeof value === "symbol";
62 }, []);
63
64 const getDescription = useCallback((symbol: symbol): string | undefined => {
65 return symbol.description;
66 }, []);
67
68 const addSymbol = useCallback((symbol: symbol) => {
69 if (!symbolsRef.current.has(symbol)) {
70 setSymbols((prev) => [...prev, symbol]);
71 symbolsRef.current.add(symbol);
72 }
73 }, []);
74
75 const removeSymbol = useCallback((symbol: symbol) => {
76 if (symbolsRef.current.has(symbol)) {
77 setSymbols((prev) => prev.filter((s) => s !== symbol));
78 symbolsRef.current.delete(symbol);
79 }
80 }, []);
81
82 const clearSymbols = useCallback(() => {
83 setSymbols([]);
84 symbolsRef.current.clear();
85 }, []);
86
87 const wellKnownSymbols = useMemo(
88 () => ({
89 iterator: Symbol.iterator,
90 asyncIterator: Symbol.asyncIterator,
91 hasInstance: Symbol.hasInstance,
92 isConcatSpreadable: Symbol.isConcatSpreadable,
93 species: Symbol.species,
94 toPrimitive: Symbol.toPrimitive,
95 toStringTag: Symbol.toStringTag,
96 unscopables: Symbol.unscopables,
97 match: Symbol.match,
98 matchAll: Symbol.matchAll,
99 replace: Symbol.replace,
100 search: Symbol.search,
101 split: Symbol.split,
102 }),
103 []
104 );
105
106 return {
107 createSymbol,
108 getGlobalSymbol,
109 getSymbolKey,
110 isSymbol,
111 getDescription,
112 wellKnownSymbols,
113 symbols,
114 addSymbol,
115 removeSymbol,
116 clearSymbols,
117 };
118}
119