使用拆分减速器更新相关状态字段的最佳方法? [英] Best way to update related state fields with split reducers?

查看:42
本文介绍了使用拆分减速器更新相关状态字段的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种理想的方法来更新我的状态树上的几个顶级字段,同时仍然保持拆分的 reducer.

I'm trying to work out the ideal way to update several top level fields on my state tree while still maintaining split reducers.

这是我想出的一个简单的解决方案.

Here's a simple solution that I've come up with.

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.

Currently I'm able to dispatch a single action {type: ADD_FILE, fileName: 'x'}, then addFile creates an action internally to send to addFileOrder and addFile.

我很好奇它是否被认为是执行以下任一操作的更好方法.

I'm curious if it is considered a better approach to do either of the below.

而是分派两个动作,一个是添加文件,然后获取它的 id,然后用 id 分派一个 ADD_TO_FILE_ORDER 动作.或者像 {type: ADD_FILE, name: 'x', id: 1} 这样的触发和动作,而不是允许 addFile 计算新的 id.这将允许我使用 combineReducers 并过滤操作类型.这个例子可能是微不足道的,但我的实际状态树有点复杂,每个添加的文件也需要添加到其他实体中.

Instead dispatch two actions, one to add a file, then get it's id and dispatch an ADD_TO_FILE_ORDER action with the id. OR Fire and action like {type: ADD_FILE, name: 'x', id: 1}, instead of allowing addFile to calculate the new id. This would allow me to use combineReducers and filter on action type. This example is probably trivial, but my actual state tree is a bit more complicated, with each file being added also needing to be added to other entities.

对于一些额外的上下文,更完整的状态树看起来像这样.

For some additional context, a more complete state tree would look like this.

{
    "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. 将每个新的 fileFrame 添加到为其创建的框架中.

最后两点让我怀疑我是否能够使用 combineReducers.

The last two points make me wonder if I'd be able to use combineReducers at all.

推荐答案

我最终找到了一个非常简单的解决方案.

I ended up finding a pretty simple solution to this problem.

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

Both of these blocks from the documentation are functionally the same thing.

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)
  };
}

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

I ended up tweaking the second block, and always passing along my global state tree. As long as nothing edits the state along the way, all the reducers work fine.

// 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)
  };
}

这篇关于使用拆分减速器更新相关状态字段的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆