如何在 redux saga 中调度操作之前将数据设置为 localStorage

Posted

技术标签:

【中文标题】如何在 redux saga 中调度操作之前将数据设置为 localStorage【英文标题】:How to set data to localStorage before dispatching action in redux saga 【发布时间】:2021-12-31 07:57:21 【问题描述】:

您好,我正在使用 redux saga 生成器功能。此功能的目的是根据用户类型登录用户。在这里,我正在检查是否有任何特定类型的用户,据此我将用户重定向到特定的route。我的问题是在发送此操作之前yield put(loginSuccess(response)),我想将令牌存储在localstorage 中,如我试过这种方式,但存储需要一些时间。我该如何解决这个问题,或者有什么方法可以在这里使用promises 或任何其他更好的解决方案来解决这个问题

function* login(obj) 
  const res = yield call(login, obj)
  if (res.data.token) 
    localStorage.setItem('token', res.data.token)
    yield put(Success(res))
    if (res.data.isAdmin == true) 
      history.push('/admin')
     else if (res.data.userType == 'student') 
      history.push('/student')
    
   else 
    yield put(Error(res.message))
  

【问题讨论】:

【参考方案1】:

从技术上讲,localStorage 应该是同步的,因此您以后不必以任何方式等待读取数据。但是,用户报告并非总是如此,如 cmets 对此 SO 问题的回答所示: Is html5 localStorage asynchronous?

从那里的另一个答案复制,这可能是问题的根本原因:

本规范不要求上述方法等到 数据已物理写入磁盘。只有在什么方面保持一致 访问相同底层键/值列表的不同脚本 需要对看到。

不幸的是,这似乎引入了一种竞争条件,当您尝试在与存储它们时相同的滴答声中读取数据时,有时数据还不会被存储。

如果您也遇到此问题,在 localStorage 行之后添加 yield delay(0) 应该可以解决问题。


解决此问题以解决任意延迟的另一种方法是在 localStorage 之上引入一个抽象层,在写入时您会将数据同时保存到 localSotrage 和内存中,而在读取时您将使用内存存储相反 - 但是,一旦您将多个打开的选项卡/窗口引入等式,这可能会变得非常复杂,因为您需要监听存储事件并在 localStorage 和内存之间进行适当的双向同步。

Google 展示了一些已经为您执行此操作的现有库: https://github.com/nbubna/store(更复杂但更健壮且经过用户测试) https://github.com/matthew-andrews/superstore-sync(轻量级,但用的人不多)

【讨论】:

以上是关于如何在 redux saga 中调度操作之前将数据设置为 localStorage的主要内容,如果未能解决你的问题,请参考以下文章

Redux-Saga ES6类语法方法在调度操作时不会被调用

如何将 redux-sagas 与 react-hooks 一起使用

redux-saga 与 redux 一起使用会导致 render() 被调用两次

“你不能把(又名 saga 中的 dispatch)冻结动作”——Redux Saga

Redux-saga

使用 redux saga 时等待 redux action 完成调度