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

Gar*_*ary 7 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})
  };
}
Run Code Online (Sandbox Code Playgroud)

目前我能够发送一个动作{type: ADD_FILE, fileName: 'x'},然后addFile在内部创建一个动作发送到addFileOrderaddFile.

我很好奇它是否被认为是更好的方法来做下面的任何一个.

而是发送两个动作,一个用于添加文件,然后获取它的id并发送ADD_TO_FILE_ORDER带有id 的动作.或消防和动作{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
            }           
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

添加文件需要:

  1. 将其添加到文件哈希.
  2. 将其添加到fileOrder数组.
  3. 为每个帧添加引用该文件的fileFrame.
  4. 将每个新文件框架添加到为其创建的框架中.

最后两点让我想知道我是否能够使用combineReducers.

Gar*_*ary 7

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

文档中的这两个块在功能上都是相同的.

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)
  };
}
Run Code Online (Sandbox Code Playgroud)

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

// Simple change to pass the entire state to each reducer.
// You have to be extra careful to keep state immutable here.
function reducer(state, action) {
  return {
    a: doSomethingWithA(state.a, action, state),
    b: processB(state.b, action, state),
    c: c(state.c, action, state)
  };
}
Run Code Online (Sandbox Code Playgroud)