mobx进行持久化封装

mobx进行持久化封装

使用场景

我在使用react+mobx进行状态管理的代码编写的时候,我发现有些数据数据需要web端持久化维护

1.不需要每次都向服务端获取的数据,例如Token,用户历史聊天记录等。

2.一些用户设置,例如,声音大小、UI主题选择、用户调整侧边栏的宽度等

如果需要对这些数据进行状态管理需要添加两部操作

1、在mobx的状态进行变化时,调用localStorage.setItem持久化存储。

2、在mobx的状态初始化时,调用localStorage.getItem获取存储值

简单封装
import { debounce } from '@/utils/common'
import { action, makeObservable, observable } from 'mobx'

const key = 'configInfoState'
/**
 * 默认值
 */
const defaultValue = {
  chatInputBoxHeight: 150,
  leftTwoBarWidth: 300,
}
/**
 * 获取本地存储的状态
 * @returns
 */
const getLocal = (): ConfigInfoStateData => {
  let data: ConfigInfoStateData
  try {
    data = JSON.parse(localStorage.getItem(key) || '')
    if (!data.chatInputBoxHeight) {
      throw new Error('parse Error')
    }
  } catch (e) {
    data = defaultValue
  }
  return data
}
/**
 * 使用防抖函数防止频繁写入本地存储
 */
const saveLocal = debounce((data: ConfigInfoStateData) => {
  localStorage.setItem(key, JSON.stringify(data))
}, 1000)

type ConfigInfoStateData = typeof defaultValue
class ConfigInfoState {
  value: ConfigInfoStateData = getLocal()
  setValue<T extends keyof ConfigInfoStateData>(
    key: T,
    value: ConfigInfoStateData[T]
  ) {
    this.value[key] = value
    saveLocal(this.value)
  }

  constructor() {
    makeObservable(this, {
      value: observable,
      setValue: action,
    })
  }
}

export const configInfoState = new ConfigInfoState()

这种简单封装可以让我们调用时无需再对持续化的工作进行考虑,但是每次使用创建一个状态都需要写一遍上面的代码,上面代码其实还可以优化,

封装优化
创建一个文件storageState.ts
import { debounce } from '@/utils/common'
import { action, makeObservable, observable } from 'mobx'

/**
 * 获取缓存值
 * @param defaultValue 获取失败的返回默认值
 * @param key 密钥
 * @returns
 */
const getLocal = <T>(defaultValue: T, key: string): T => {
  let data: T
  try {
    const str = localStorage.getItem(key)
    if (!str) {
      return defaultValue
    }
    data = JSON.parse(str)
    if (data == null) {
      return defaultValue
    }
  } catch (e) {
    data = defaultValue
  }
  return data
}
class StorageState<T extends object> {
  value: T
  private key: string
  private defaultValue: T
  private saveLocal: (data: T) => void
  setValue<K extends keyof T>(key: K, value: T[K]) {
    this.value[key] = value
    this.saveLocal(this.value)
  }
  clear() {
    this.value = this.defaultValue
    this.saveLocal(this.value)
  }
  /**
   *
   * @param key 缓存密钥
   * @param defaultValue 默认值
   * @param persistenceDelay 持久化延迟
   */
  constructor(key: string, defaultValue: T, persistenceDelay: number = 1000) {
    if (defaultValue === null) {
      throw new Error('new StorageState param defaultValue cannot be null')
    }
    this.key = '_storage_state_' + key
    if (key.length < 5) {
      console.log('key too short, please use a longer key')
    }

    this.value = getLocal<T>(defaultValue, this.key)
    this.defaultValue = defaultValue
    if (persistenceDelay <= 0) {
      this.saveLocal = <T>(data: T) =>
        localStorage.setItem(this.key, JSON.stringify(data))
    } else {
      this.saveLocal = debounce(
        <T>(data: T) => localStorage.setItem(this.key, JSON.stringify(data)),
        persistenceDelay
      )
    }

    makeObservable(this, {
      value: observable,
      setValue: action,
    })
  }
}
export default StorageState
修改原来的configInfoState
import StorageState from '@/utils/StorageState'

const key = 'configInfoState'
const defaultValue = {
  chatInputBoxHeight: 150,
  leftTwoBarWidth: 300,
}

export const configInfoState = new StorageState(key, defaultValue)

这时候每次创建一个状态时,只需要初始化默认值和key的命名就可以了

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序老六

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值