【问题标题】:How to update redux state further down the tree如何在树的下方更新 redux 状态
【发布时间】:2016-09-30 13:03:57
【问题描述】:

对于给定的 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 } }) 也不太可读。

【问题讨论】:

标签: javascript ecmascript-6 redux


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    你可以选择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
                    };
                }
        }
    };
    

    【讨论】:

      【解决方案3】:

      是的,这实际上是 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 }
      

      最后一个选择器的数据会在收到响应后自动更新——所以不需要手动写这些东西。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-08
        • 2021-12-24
        • 2020-08-07
        • 2018-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多