useSessionStorageState
作用
将状态存储在 sessionStorage
中的 Hook。 用法与 useLocalStorageState
一致。
原理
通过
createUseStorageState
创建useSessionStorageState
,然后通过useState
做数据状态的存储与改变,然后与sessionStorage
做数据的同步
源码
ts
import { createUseStorageState } from '../createUseStorageState'
import isBrowser from '../utils/isBrowser'
const useSessionStorageState = createUseStorageState(() => (isBrowser ? sessionStorage : undefined))
export default useSessionStorageState
createUseStorageState
ts
import { useState } from 'react'
import useMemoizedFn from '../useMemoizedFn'
import useUpdateEffect from '../useUpdateEffect'
import { isFunction, isUndef } from '../utils'
export type SetState<S> = S | ((prevState?: S) => S)
export interface Options<T> {
defaultValue?: T | (() => T)
serializer?: (value: T) => string
deserializer?: (value: string) => T
onError?: (error: unknown) => void
}
export function createUseStorageState(getStorage: () => Storage | undefined) {
function useStorageState<T>(key: string, options: Options<T> = {}) {
let storage: Storage | undefined
const {
onError = (e) => {
console.error(e)
}
} = options
// https://github.com/alibaba/hooks/issues/800
try {
// 如果传入的是函数,则执行函数
storage = getStorage()
} catch (err) {
onError(err)
}
// 序列化,如果传入了序列化函数,则执行序列化函数,否则使用JSON.stringify
const serializer = (value: T) => {
if (options.serializer) {
return options.serializer(value)
}
return JSON.stringify(value)
}
// 反序列化,如果传入了反序列化函数,则执行反序列化函数,否则使用JSON.parse
const deserializer = (value: string): T => {
if (options.deserializer) {
return options.deserializer(value)
}
return JSON.parse(value)
}
// 获取存储的值
function getStoredValue() {
try {
// 从storage中获取key对应的值
const raw = storage?.getItem(key)
if (raw) {
// 如果存在,则执行反序列化函数
return deserializer(raw)
}
} catch (e) {
onError(e)
}
// 如果不存在,则执行默认值函数
if (isFunction(options.defaultValue)) {
return options.defaultValue()
}
// 直接返回默认值
return options.defaultValue
}
// 使用useState存储状态值
const [state, setState] = useState(getStoredValue)
// 使用useUpdateEffect监听key的变化,如果key变化,则更新状态
useUpdateEffect(() => {
setState(getStoredValue())
}, [key])
// 更新状态方法
const updateState = (value?: SetState<T>) => {
// 如果传入的是函数,则执行函数
const currentState = isFunction(value) ? value(state) : value
// 更新状态
setState(currentState)
// 如果状态为undefined,则从storage中移除key对应的值
if (isUndef(currentState)) {
storage?.removeItem(key)
} else {
try {
// 否则,将状态序列化后存储到storage中
storage?.setItem(key, serializer(currentState))
} catch (e) {
console.error(e)
}
}
}
// 返回状态和更新状态方法
return [state, useMemoizedFn(updateState)] as const
}
return useStorageState
}