Skip to content

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
}

如有转载或 CV 的请标注本站原文地址