streamich/react-use · error · Error
useLocalStorage key may not be falsy
Error message
useLocalStorage key may not be falsy
What it means
Thrown by useLocalStorage when its `key` argument is falsy. The hook runs an SSR short-circuit first (returns [initialValue, noop, noop] when not in a browser), so this check only executes client-side; once there, any falsy key (empty string '', 0, false, null, undefined, NaN) is rejected because localStorage cannot be keyed by such a value. Passing a non-string key would also fail at the storage API, so the library fails fast with a clear message instead.
Source
Thrown at src/useLocalStorage.ts:23
| {
raw: true;
}
| {
raw: false;
serializer: (value: T) => string;
deserializer: (value: string) => T;
};
const useLocalStorage = <T>(
key: string,
initialValue?: T,
options?: parserOptions<T>
): [T | undefined, Dispatch<SetStateAction<T | undefined>>, () => void] => {
if (!isBrowser) {
return [initialValue as T, noop, noop];
}
if (!key) {
throw new Error('useLocalStorage key may not be falsy');
}
const deserializer = options
? options.raw
? (value) => value
: options.deserializer
: JSON.parse;
// eslint-disable-next-line react-hooks/rules-of-hooks
const initializer = useRef((key: string) => {
try {
const serializer = options ? (options.raw ? String : options.serializer) : JSON.stringify;
const localStorageValue = localStorage.getItem(key);
if (localStorageValue !== null) {
return deserializer(localStorageValue);
} else {
initialValue && localStorage.setItem(key, serializer(initialValue));View on GitHub (pinned to fbe99c6327)
Solutions
- Provide a stable, non-empty string key: useLocalStorage(`item-${id}`, initialValue) and ensure the interpolated value is defined.
- Guard before calling: if (!key) return fallback; else call the hook — or compute key with a guaranteed prefix/default.
- If the key depends on async data, render the component using useLocalStorage only after the key is known (conditional rendering), or lift the key to a parent.
- Stringify numeric ids and avoid using 0/false as keys.
Example fix
// before
useLocalStorage(userId, defaultPrefs); // userId may be 0 or undefined
useLocalStorage(maybeKey, defaultPrefs); // maybeKey may be '' or undefined
// after
useLocalStorage(`user:${userId}`, defaultPrefs);
// or skip until known:
if (!maybeKey) return <Fallback/>;
useLocalStorage(maybeKey, defaultPrefs); Defensive patterns
Strategy: validation
Validate before calling
function useLocalStorageSafe<T>(key: string, initial?: T, opts?: parserOptions<T>) {
if (!key || typeof key !== 'string') {
throw new Error('useLocalStorage requires a non-empty string key');
}
return useLocalStorage<T>(key, initial, opts);
}
// or coerce at the call site:
const storageKey = key ? `ns:${key}` : 'ns:default';
const [val, setVal] = useLocalStorage(storageKey, initial); Type guard
const isStorageKey = (v: unknown): v is string =>
typeof v === 'string' && v.length > 0;
if (isStorageKey(key)) {
const [val, setVal] = useLocalStorage(key, initial);
}
// else branch: key not ready — render a fallback / skip the hook Try / catch
// Hooks cannot be wrapped in try/catch around the call cleanly; instead guard the
// key before calling. If you must isolate, render the hook behind a gate:
{hasKey ? <UsesLocalStorage/> : <Fallback/>} Prevention
- Always namespace and stringify keys (e.g. `app:user:${id}`) so they are never empty or falsy.
- Derive keys only from values that are guaranteed defined (avoid optional props without a default).
- When a key depends on async data, gate the component rendering the hook until the key is known.
- Never pass 0, false, null, or '' as a key.
When it happens
Trigger: Calling useLocalStorage(key, initialValue, options) where key evaluates to a falsy value: an empty string, undefined (e.g. from an unset prop/env), null, 0, or false. Typically the key is derived from a prop, route param, or config that has not resolved yet.
Common situations: Key built from an optional prop (id ?? '') producing ''; reading a key from env/config that is undefined in some environments; dynamic keys computed before data loads; passing a numeric id (0 is falsy) instead of a stringified storage key.
Related errors
- states expected to be an object or array, got ${typeof state
- State '${state}' is not a valid state (does not exist in sta
- Capacity has to be greater than 1, got '${capacity}'
- useReducerContext must be used inside a ReducerProvider.
- useStateContext must be used inside a StateProvider.
AI-assisted analysis of streamich/react-use@fbe99c6327 (2026-08-12).
Data as JSON: /api/errors/3355963164eea400.
Report an issue: GitHub.