【问题标题】:Avoiding repeating state names避免重复州名
【发布时间】:2016-11-28 19:09:35
【问题描述】:

假设我有一个 rootreducer,如下所示。

const rootR = combineReducers({
  topics,
  ...
});

主题 reducer

function topics(state = { topics=[], error: null}, action){
  switch (action.type){
    case types.FETCH_TOPICS_SUCCESSFULLY:
      const { topics } = action;
      return {
        ...state,
        topics,
      };
    default:
      return state;
  }
};

当我触发相关操作时,我会使用可重复属性 state.topics.topics 而不是 state.topics 获得我的状态

有什么办法可以避免这种重复(topics.topics)?

提前致谢

【问题讨论】:

  • const { topics } = action; 这里的主题对象是什么样的?
  • @finalfreq 这是对象数组,例如 > {userId, theme, body}

标签: javascript reactjs ecmascript-6 redux


【解决方案1】:

查看topics reducer 的initialState,topics reducer 可访问的状态对象具有以下结构:

{
    topics: [],
    error: null
}

所以当你像这样combineReducers 时:

const rootR = combineReducers({
  topics,
  anotherReducer,
  someOtherReducer.
  // ...
});

产生的全局应用状态将如下所示:

{
    topics: {
        topics: [],
        error: null
    },
    anotherReducer: {
        // ...
    },
    someOtherReducer: {
        // ...
    },

    // ...        
}

所以如果你想从全局状态访问topics数组,你需要做state.topics.topics

state.topics 下有两个东西,topicserror 的数组。 因此,让我们将第二个 topics 键重命名为 items 以避免混淆。 (因为你也想要error,所以有第二个key来存储数组是不可避免的)

因此我们有:

state.topics = {
    items: [],
    error: null,
}

现在我们访问的是state.topics.items,而不是state.topics.topics

要实现这一点,传递给topics reducer 的初始状态必须是:

function topics(state = { items = [], error: null }, action){
    //...
}

现在在 reducer FETCH_TOPICS_SUCCESSFULLY 中,我们想将数组 action.topics 附加到 items,如下所示(不改变当前状态):

case types.FETCH_TOPICS_SUCCESSFULLY:
    const { topics } = action;
    return {
        ...state,
        items: [
            ...state.items,
            ...topics
        ],
    };

【讨论】:

    【解决方案2】:

    @markerikson 是对的,函数中传递的state 变量实际上是topics,一旦调用了FETCH_TOPICS_SUCCESSFULLY,所以最好在那里做return topics。 但鉴于您的情况,您也可以返回Object.assign({}, state, topics),而不是返回{...state, topics}return topics。这将创建一个新对象,其中包含先前状态和主题的所有属性合并在一起。

    【讨论】:

      【解决方案3】:

      你是双重嵌套的东西。 topics reducer 只会看到状态的“主题”切片。所以,不要返回{...state, topics},而是返回return topics

      更新

      您对问题的编辑大大改变了情况。

      原来,你有:

      function topics(state = {}, action){
      

      现在,你有:

      function topics(state = { topics=[], error: null}, action){
      

      我承认在这一点上我对你想要的状态结构实际上应该是什么感到有些困惑。

      查看您的原始定义,您似乎误解了combineReducers 的工作原理,并且重复地尝试返回一个包含名为“topics”的字段/切片的新对象。现在,看起来根级“主题”切片本身也有一个名为“主题”的字段。

      topicserror 是否应该位于状态树的 中?或者,它们真的都应该是顶级“主题”切片的一部分吗?如果这确实是您想要的,那么您已将状态树定义为需要为topics.topics

      另外,回答@free-soul:不,在原始示例中,return topics 不会改变状态,因为它只是返回动作中的任何内容。即使action.topic 字段实际上与该状态中的数组相同,结果也只是空操作。

      【讨论】:

      • 我必须返回一个对象。现在我不处理错误,但我将来会处理。有意义吗?
      • @markerikson, return topics 将改变状态。同样在原始问题中,他有 state.topics 一个对象,而 action.topics 是一个数组。
      • @markerikson,我想我将不得不不同意。 topics reducer 可访问的状态是 { topics: [ item1, item2, ...], error: null }。考虑action.topics = [item3, item4]。因此,如果你从 reducer 执行 const { topics } = action;,然后执行 return topics,则结果状态将为 [item3, item4]。状态变成了一个数组,你会丢失topicserror 中的先前项。这有意义吗?
      • @free-soul :我的原始响应基于原始示例代码,其中state 参数标记为topics 一个数组。无论哪种方式,return topics 本身都不是“突变”,因为“突变”是对现有对象或数组引用的直接修改。 topics.push() 是“突变”的一个例子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-18
      • 2021-08-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      相关资源
      最近更新 更多