Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Redux 用于处理不同步的规范化状态的Reducer代码_Redux - Fatal编程技术网

Redux 用于处理不同步的规范化状态的Reducer代码

Redux 用于处理不同步的规范化状态的Reducer代码,redux,Redux,假设我有一个规范化的状态,它看起来像这样,比如说一个待办事项列表: { ids: [1,2,3,4], dataEntities: { 1: { //the todo item name, content, due date, etc}, 2: { //same } //etc.. }, metadataEntities: { 1: { //info about when the todo was last edited, saved to

假设我有一个规范化的状态,它看起来像这样,比如说一个待办事项列表:

{
  ids: [1,2,3,4],
  dataEntities: {
     1: { //the todo item name, content, due date, etc},
     2: { //same }
     //etc..
  },
  metadataEntities: {
     1: { //info about when the todo was last edited, saved to server, etc }
     // etc..
  }
}
当然,我已经编写了我的简化程序,因此每当我从
ids
添加或删除某些内容时,我也会更新
dataEntities
metadataEntities
中的相应条目。因此,我的状态应该始终保持一致,即如果
ids
中存在某个内容,那么它将在每个实体中都有条目。因此,依赖于这种一致性的减速器应该可以正常工作

例如,像这样的reducer操作应该可以(假设我使用的是RTK或Immer,所以编写一个明显的状态变化reducer是可以的):

换句话说,
if
块中的语句应该是正确的。如果id存在于
ids
中,则它应该在state.dataEntities和state.metaDataEntities中具有相应的实体。事实上,如果设置和维护这些实体的初始值设定项和还原项都被正确编写,那么情况将永远如此

但是。。。如果不是呢?一段杂乱的代码、一个奇怪的边缘案例等等——由于某种原因,事情变得“不同步”,即
ids
中的一个id在其中一个实体数组中没有对应的实体。redux中减速器处理该问题的“正确”方法是什么

换句话说,我应该如何在此处填写缺失的代码:

const reducer = (state, action) => {
  switch(action.type) {
    //...
    "editTodo":
      const id = action.payload.id
      const newTodoContent = action.payload.content
      if(state.ids.includes(id)) {
        if(state.dataEntities[id] === undefined || state.metadataEntities[id] === undefined
        {
          //WHAT GOES HERE?
        }
        state.dataEntities[id].content = newTodoContent
        state.metaDataEntities[id].lastEdit = new Date().toString()
      } else return
   }
}
我考虑过几个选择:

  • 返回不变状态。这看起来很好,从一个纯粹的重复 透视图,但在发现我的 应用程序不工作。(为什么不更新待办事项?)

  • 扔。这是否定的,因为这是一个减速器,它需要是一个纯函数

  • 在reducer之外执行一些日志记录或错误通知,例如在中间件中。好吧,但这并不是真正的答案 问题--我正试图找出如何编写安全的减速机 处理代码中可能存在问题的代码 减速器外部(包括中间件)

  • 保存错误的状态变量。这是到目前为止我想到的最好的方法,也就是说,让一个变量或对象处于 如果reducer运行到不一致的状态,它可以登录到。那么 “WHAT GOES HERE”行看起来像
    state.stateError=“Inconsistent entity state”
    (或者更具体的东西,理想情况下)

  • 是否有针对此类情况的推荐或最佳实践解决方案


    非常感谢。

    作为第一个观察,请注意这将为您完成大部分规范化更新工作。@markerikson,绝对是。事实上,我一直很难理解RTK如何处理这种情况,也就是说,在没有相应实体的情况下,可以要求reducer更新id。在我看来,从源代码(我可能读错了)来看,如果要求它更新一个没有相应实体的id,它只是不更新,而不是指示错误。也许这绝对是正确的方法,但这也是导致这个问题的部分原因。(同样,如果不感谢您在RTK上所做的所有工作,就不能不发表这一评论!)是的,还原程序应该确定响应任何给定操作的状态更新,并且“此操作没有更新”是完全有效的结果,即使它是还原程序确实关心的操作。这也适用于将动作建模为“事件”的建议方法。但是,这仍然取决于您决定这是否是您希望减缩器具有的语义。(哦,还有:谢谢,不客气!)
    const reducer = (state, action) => {
      switch(action.type) {
        //...
        "editTodo":
          const id = action.payload.id
          const newTodoContent = action.payload.content
          if(state.ids.includes(id)) {
            if(state.dataEntities[id] === undefined || state.metadataEntities[id] === undefined
            {
              //WHAT GOES HERE?
            }
            state.dataEntities[id].content = newTodoContent
            state.metaDataEntities[id].lastEdit = new Date().toString()
          } else return
       }
    }