useLocalStorageState

将状态存储在 localStorage 中的 Hook,页面刷新后状态依然保持。

基础用法

import { useLocalStorageState } from 'miaoma-rhooks'
import React from 'react'

function Demo() {
    const [message, setMessage] = useLocalStorageState('use-local-storage-state-demo', {
        defaultValue: '你好,世界!'
    })

    return (
        <div>
            <input value={message || ''} onChange={e => setMessage(e.target.value)} placeholder="请输入内容" style={{ width: 300 }} />
            <button onClick={() => setMessage('你好,世界!')}>重置</button>
        </div>
    )
}

API

const [state, setState] = useLocalStorageState<T>(
  key: string,
  options?: {
    defaultValue?: T | (() => T);
    serializer?: (value: T) => string;
    deserializer?: (value: string) => T;
  }
);

Params

参数 说明 类型 默认值
key localStorage 的键名 string -
options 配置项 Options<T> -

Options

参数 说明 类型 默认值
defaultValue 默认值,会在 localStorage 中没有值的时候使用 T | (() => T) undefined
serializer 自定义序列化方法 (value: T) => string JSON.stringify
deserializer 自定义反序列化方法 (value: string) => T JSON.parse

Result

参数 说明 类型
state 当前状态 T
setState 设置状态的函数 StorageStateResult<T>

进阶用法

存储复杂数据结构

import { useLocalStorageState } from 'miaoma-rhooks'
import React from 'react'

function ComplexDataDemo() {
    const [user, setUser] = useLocalStorageState('user-info', {
        defaultValue: {
            name: '张三',
            age: 18,
            address: {
                city: '北京',
                district: '朝阳区'
            },
            tags: ['程序员', 'React']
        }
    })

    return (
        <div>
            <pre>{JSON.stringify(user, null, 2)}</pre>
            <button
                onClick={() =>
                    setUser({
                        ...user,
                        age: user.age + 1,
                        tags: [...user.tags, '前端']
                    })
                }
            >
                修改信息
            </button>
            <button
                onClick={() =>
                    setUser({
                        name: '张三',
                        age: 18,
                        address: {
                            city: '北京',
                            district: '朝阳区'
                        },
                        tags: ['程序员', 'React']
                    })
                }
            >
                重置
            </button>
        </div>
    )
}

自定义序列化和反序列化

import { useLocalStorageState } from 'miaoma-rhooks'
import React from 'react'

function CustomSerializerDemo() {
    const [user, setUser] = useLocalStorageState('custom-serializer-demo', {
        defaultValue: { name: '张三', birthday: new Date() },
        // 自定义序列化,处理 Date 对象
        serializer: value =>
            JSON.stringify({
                ...value,
                birthday: value.birthday.toISOString()
            }),
        // 自定义反序列化,还原 Date 对象
        deserializer: value => {
            const parsed = JSON.parse(value)
            return {
                ...parsed,
                birthday: new Date(parsed.birthday)
            }
        }
    })

    return (
        <div>
            <p>姓名: {user.name}</p>
            <p>生日: {user.birthday.toLocaleDateString()}</p>
            <button
                onClick={() =>
                    setUser({
                        ...user,
                        birthday: new Date()
                    })
                }
            >
                更新生日为今天
            </button>
        </div>
    )
}

监听其他标签页的变化

import { useLocalStorageState } from 'miaoma-rhooks'
import React, { useEffect } from 'react'

function SyncTabsDemo() {
    const [message, setMessage] = useLocalStorageState('sync-tabs-demo', {
        defaultValue: ''
    })

    useEffect(() => {
        const handleStorageChange = e => {
            if (e.key === 'sync-tabs-demo') {
                // 当其他标签页修改了 localStorage 时,会触发这个事件
                console.log('其他标签页修改了数据:', e.newValue)
            }
        }

        window.addEventListener('storage', handleStorageChange)
        return () => {
            window.removeEventListener('storage', handleStorageChange)
        }
    }, [])

    return (
        <div>
            <p>当前消息: {message}</p>
            <input value={message || ''} onChange={e => setMessage(e.target.value)} placeholder="请输入内容" />
            <p>提示: 打开多个标签页,在一个标签页中修改内容,其他标签页会自动同步</p>
        </div>
    )
}