使用拆分缩减器更新相关状态字段的最佳方法?

时间:2015-10-24 17:50:17

标签: reducers redux

我试图找到理想的方法来更新状态树上的几个顶级字段,同时仍保持拆分缩减器。

这是我提出的一个简单的解决方案。

var state = {
  fileOrder: [0],
  files: {
    0:{
      id: 0,
      name: 'asdf'
    }
  }
};

function handleAddFile(state, action) {
  return {...state, ...{[action.id]:{id: action.id, name: action.name}}};
};

function addFileOrder(state, action) {
  return [...state, action.id];
}

// Adding a file should create a new file, and add its id to the fileOrder array.
function addFile(state, action) {
  let id = Math.max.apply(this, Object.keys(state.files)) + 1;
  return {
    ...state,
    fileOrder: addFileOrder(state.fileOrder, {id}),
    files: handleAddFile(state.files, {id, name: action.name})
  };
}

目前,我可以发送单个操作{type: ADD_FILE, fileName: 'x'},然后addFile在内部创建一个操作,以便发送到addFileOrderaddFile

我很好奇是否认为这是下列任何一种方法的更好方法。

而是发送两个动作,一个用于添加文件,然后获取它的ID并使用id发送ADD_TO_FILE_ORDER动作。 或消防和{type: ADD_FILE, name: 'x', id: 1}之类的操作,而不是允许addFile计算新ID。这将允许我使用combineReducers并过滤操作类型。 这个例子可能很简单,但我的实际状态树有点复杂,每个文件的添加也需要添加到其他实体。

对于某些其他上下文,更完整的状态树将如下所示。

{
    "fileOrder": [0]
    "entities": {
        "files": {
            0: {
                id: 0,
                name: 'hand.png'
            }
        },
        "animations": {
            0: {
                id: 0,
                name: "Base",
                frames: [0]
            }
        },
        "frames": {
            0: {
                id: 0,
                duration: 500,
                fileFrames: [0]
            }
        },
        "fileFrames": {
            0: {
                id: 0,
                file: 0,
                top: 0,
                left: 0,
                visible: true
            }           
        }
    }
}

添加文件需要:

  1. 将其添加到文件哈希。
  2. 将其添加到fileOrder数组。
  3. 为每个框架添加引用该文件的文件框架。
  4. 将每个新文件框架添加到为其创建的框架中。
  5. 最后两点让我想知道我是否能够使用combineReducers。

2 个答案:

答案 0 :(得分:7)

我最终找到了解决这个问题的非常简单的方法。

文档中的这两个块在功能上都是一样的。

opacity:1!important

我最后调整了第二个块,并且总是传递我的全局状态树。只要沿途没有任何编辑状态,所有减速器都可以正常工作。

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
});

// This is functionally equivalent.
function reducer(state, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  };
}

答案 1 :(得分:2)

以作者的解决方案为基础:

我一直有同样的问题,我需要(只是一点点)访问我的减速机部分状态。我认为这个解决方案可以在实践中发挥作用,如果你努力不改变除了标志或计数器等单一价值之外的任何东西。

如果其他开发人员没有像他们的代码那样保留,那么它的杂质就会变得疯狂。想象一下,如果开始改变b和c的状态部分,b改变a和c的部分,等等会发生什么。

您可能会考虑缩小杂质的表面积,如下所示:

function reducer(state, action) {
  return {
    a: doSomethingWithA(state.a, action, state.globals),
    b: processB(state.b, action, state.globals),
    c: c(state.c, action, state.globals)
  };
}