
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
react-storage-hooks
Advanced tools
Custom React hooks for keeping application state in sync with localStorage
or sessionStorage
.
:book: Familiar API. You already know how to use this library! Replace useState
and useReducer
hooks with the ones in this library and get persistent state for free.
:sparkles: Fully featured. Automatically stringifies and parses values coming and going to storage, keeps state in sync between tabs by listening to storage events and handles non-straightforward use cases correctly.
:zap: Tiny and fast. Less than 700 B gzipped. No external dependencies. Only reads from storage when necessary and always writes to storage after rendering.
:capital_abcd: Completely typed. Written in TypeScript. Type definitions included.
:muscle: Backed by tests. Full coverage of the API.
You need to use version 16.8.0 or greater of React, since that's the first one to include hooks. If you still need to create your application, Create React App is the officially supported way.
Add the package to your React project:
npm install --save react-storage-hooks
Or with yarn:
yarn add react-storage-hooks
The useStorageState
and useStorageReducer
hooks included in this library work like useState
and useReducer
. The only but important differences are:
Storage
object (localStorage
or sessionStorage
) and storage key.undefined
, and will be updated with Error
objects thrown by Storage.setItem
. However the hook will keep updating state even if new values fail to be written to storage, to ensure that your application doesn't break.useStorageState
import React from 'react';
import { useStorageState } from 'react-storage-hooks';
function StateCounter() {
const [count, setCount, writeError] = useStorageState(
localStorage,
'state-counter',
0
);
return (
<>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
{writeError && (
<pre>Cannot write to localStorage: {writeError.message}</pre>
)}
</>
);
}
function useStorageState<S>(
storage: Storage,
key: string,
defaultState?: S | (() => S)
): [S, React.Dispatch<React.SetStateAction<S>>, Error | undefined];
useStorageReducer
import React from 'react';
import { useStorageReducer } from 'react-storage-hooks';
function reducer(state, action) {
switch (action.type) {
case 'inc':
return { count: state.count + 1 };
case 'dec':
return { count: state.count - 1 };
default:
return state;
}
}
function ReducerCounter() {
const [state, dispatch, writeError] = useStorageReducer(
localStorage,
'reducer-counter',
reducer,
{ count: 0 }
);
return (
<>
<p>You clicked {state.count} times</p>
<button onClick={() => dispatch({ type: 'inc' })}>+</button>
<button onClick={() => dispatch({ type: 'dec' })}>-</button>
{writeError && (
<pre>Cannot write to localStorage: {writeError.message}</pre>
)}
</>
);
}
function useStorageReducer<S, A>(
storage: Storage,
key: string,
reducer: React.Reducer<S, A>,
defaultState: S
): [S, React.Dispatch<A>, Error | undefined];
function useStorageReducer<S, A, I>(
storage: Storage,
key: string,
reducer: React.Reducer<S, A>,
defaultInitialArg: I,
defaultInit: (defaultInitialArg: I) => S
): [S, React.Dispatch<A>, Error | undefined];
The storage
parameter of the hooks can be any object that implements the getItem
, setItem
and removeItem
methods of the Storage
interface. Keep in mind that storage values will be automatically serialized and parsed before and after calling these methods.
interface Storage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
}
This library checks for the existence of the window
object and even has some tests in a node-like environment. However in your server code you will need to provide a storage object to the hooks that works server-side. A simple solution is to use a dummy object like this:
const dummyStorage = {
getItem: () => null,
setItem: () => {},
removeItem: () => {},
};
The important bit here is to have the getItem
method return null
, so that the default state parameters of the hooks get applied as initial state.
If you're using a few hooks in your application with the same type of storage, it might bother you to have to specify the storage object all the time. To alleviate this, you can write a custom hook like this:
import { useStorageState } from 'react-storage-hooks';
export function useLocalStorageState(...args) {
return useStorageState(localStorage, ...args);
}
And then use it in your components:
import { useLocalStorageState } from './my-hooks';
function Counter() {
const [count, setCount] = useLocalStorageState('counter', 0);
// Rest of the component
}
This library is MIT licensed.
FAQs
React hooks for persistent state
We found that react-storage-hooks demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.