astoilkov / use-local-storage-state

React hook that persists data in localStorage
MIT License
1.11k stars 41 forks source link
hook localstorage persistent react usestate

use-local-storage-state

React hook that persist data in localStorage

Downloads Gzipped Size Build Status

Install

React 18 and above:

npm install use-local-storage-state

⚠️ React 17 and below. For docs, go to the react-17 branch.

npm install use-local-storage-state@17

Why

Usage

import useLocalStorageState from 'use-local-storage-state'

export default function Todos() {
    const [todos, setTodos] = useLocalStorageState('todos', {
        defaultValue: ['buy avocado', 'do 50 push-ups']
    })
}
Todo list example

```tsx import React, { useState } from 'react' import useLocalStorageState from 'use-local-storage-state' export default function Todos() { const [todos, setTodos] = useLocalStorageState('todos', { defaultValue: ['buy avocado'] }) const [query, setQuery] = useState('') function onClick() { setQuery('') setTodos([...todos, query]) } return ( <> setQuery(e.target.value)} /> {todos.map(todo => (
{todo}
))} ) } ```
Notify the user when localStorage isn't saving the data using the isPersistent property

There are a few cases when `localStorage` [isn't available](https://github.com/astoilkov/use-local-storage-state/blob/7db8872397eae8b9d2421f068283286847f326ac/index.ts#L3-L11). The `isPersistent` property tells you if the data is persisted in `localStorage` or in-memory. Useful when you want to notify the user that their data won't be persisted. ```tsx import React, { useState } from 'react' import useLocalStorageState from 'use-local-storage-state' export default function Todos() { const [todos, setTodos, { isPersistent }] = useLocalStorageState('todos', { defaultValue: ['buy avocado'] }) return ( <> {todos.map(todo => (
{todo}
))} {!isPersistent && Changes aren't currently persisted.} ) } ```
Removing the data from localStorage and resetting to the default

The `removeItem()` method will reset the value to its default and will remove the key from the `localStorage`. It returns to the same state as when the hook was initially created. ```tsx import useLocalStorageState from 'use-local-storage-state' export default function Todos() { const [todos, setTodos, { removeItem }] = useLocalStorageState('todos', { defaultValue: ['buy avocado'] }) function onClick() { removeItem() } } ```
Why my component renders twice?

If you are hydrating your component (for example, if you are using Next.js), your component might re-render twice. This is behavior specific to React and not to this library. It's caused by the `useSyncExternalStore()` hook. There is no workaround. This has been discussed in the issues: https://github.com/astoilkov/use-local-storage-state/issues/56. If you want to know if you are currently rendering the server value you can use this helper function: ```ts function useIsServerRender() { return useSyncExternalStore(() => { return () => {} }, () => false, () => true) } ```

API

useLocalStorageState(key: string, options?: LocalStorageOptions)

Returns [value, setValue, { removeItem, isPersistent }] when called. The first two values are the same as useState(). The third value contains two extra properties:

key

Type: string

The key used when calling localStorage.setItem(key) and localStorage.getItem(key).

⚠️ Be careful with name conflicts as it is possible to access a property which is already in localStorage that was created from another place in the codebase or in an old version of the application.

options.defaultValue

Type: any

Default: undefined

The default value. You can think of it as the same as useState(defaultValue).

options.defaultServerValue

Type: any

Default: undefined

The default value while server-rendering and hydrating. If not set, it will use defaultValue option instead. Set only if you want it to be different than the client value.

options.storageSync

Type: boolean

Default: true

Setting to false doesn't subscribe to the Window storage event. If you set to false, updates won't be synchronized across tabs, windows and iframes.

options.serializer

Type: { stringify, parse }

Default: JSON

JSON does not serialize Date, Regex, or BigInt data. You can pass in superjson or other JSON-compatible serialization library for more advanced serialization.

Related