如何在树

时间:2016-09-30 13:03:57

标签: javascript ecmascript-6 redux

对于给定的reducer,我的redux状态树通常看起来像这样:

{
  someField: 'some value',
  // ... more fields
  metadata: {
    pending: false,
    fetched: true,
  }
}

通常,当我执行异步请求时,我会触发SOME_ACTION_REQUEST操作,该操作会将metadata.pending属性设置为true。当匹配的SOME_ACTION_RESPONSESOME_ACTION_ERROR事件稍后发生时,它会再次重置为false。

但是,我更新状态的方式有点冗长:

case actions.SOME_ACTION_REQUEST: {
  return {
    ...state,
    metadata: { ...state.metadata, pending: true },
  };
}

有更简单的方法吗?

Object.assign({}, state, { metadata: { pending: true } })也不是非常易读。

3 个答案:

答案 0 :(得分:2)

这是进行不可变数据更新的典型示例。您可能需要仔细阅读Redux文档的新Structuring Reducers部分,以获取更多信息,尤其是Prerequisite ConceptsImmutable Update Patterns页。

答案 1 :(得分:1)

您可以使用reducer的嵌套结构。

其中有一个函数/ reducer命名元数据,调用它来更改字段。

示例代码

const metadata = (state = [], action = {}) => {
    switch (action.type) {
        case actions.SOME_ACTION_REQUEST::
            return {...state, ...action.payload.metadata};

        default:
            return state;
    }
};
const someReducer = (state = initalState, action = {}) => {
    let metadata = {};
    switch (action.type) {
        case actions.SOME_ACTION_REQUEST: {
            metadata = metadata(state.metadata, action)
            return {
                ...state,
                ...metadata
                };
            }
    }
};

答案 2 :(得分:0)

是的,它实际上是Redux的缺点,不仅如此 - 如果您使用MobX,您也会遇到同样的问题。所以,答案只是以某种方式概括它 - 编写一个reducers工厂,它将常量作为参数,并将它们合并一次,并将其重用于所有异步操作。

I've created a library对于这个问题,请随时查看。另外,请记住,原始Redux无论如何都非常冗长,并尝试以最佳方式掌握您的域模型。 您的示例将如下所示:

import { createTile } from 'redux-tiles';

const someTile = createTile({
  type: ['some', 'example'],
  fn: ({ api, params }) => api.get('/some/request', params),
});

dispatch(actions.some.example(params));
selectors.some.example(state)); // { isPending: true, error: null, data: null }

来自最后一个选择器的数据将在获得响应后自动更新 - 因此无需手动编写此类内容。

另一个问题是嵌套更新,你必须做同样的事情,但是我总是试图解决更多的冗长问题。但是,当然,它是一个非常简单的库,只尝试覆盖简单的用例 - 对于复杂的用例,我绝对建议你尝试定制的东西。