(length: number, prefix: string)
| 16 | * @param prefix Key prefix string (e.g. `'item'` → `'item-0'`, `'item-1'`, …) |
| 17 | */ |
| 18 | export function useStableKeys(length: number, prefix: string): { keys: string[]; removeKey: (index: number) => void } { |
| 19 | const idCounterRef = useRef(0) |
| 20 | |
| 21 | const [itemKeys, setItemKeys] = useState<string[]>(() => { |
| 22 | const initial: string[] = [] |
| 23 | while (initial.length < length) { |
| 24 | initial.push(`${prefix}-${idCounterRef.current++}`) |
| 25 | } |
| 26 | return initial |
| 27 | }) |
| 28 | |
| 29 | let effectiveKeys = itemKeys |
| 30 | |
| 31 | if (effectiveKeys.length < length) { |
| 32 | const nextKeys = [...effectiveKeys] |
| 33 | while (nextKeys.length < length) { |
| 34 | nextKeys.push(`${prefix}-${idCounterRef.current++}`) |
| 35 | } |
| 36 | setItemKeys(nextKeys) |
| 37 | effectiveKeys = nextKeys |
| 38 | } |
| 39 | |
| 40 | const removeKey = useCallback((index: number) => { |
| 41 | setItemKeys((prev) => prev.filter((_, i) => i !== index)) |
| 42 | }, []) |
| 43 | |
| 44 | return { keys: effectiveKeys, removeKey } |
| 45 | } |
no outgoing calls
no test coverage detected