网站搜索

reactjs - 更新 redux 中嵌套对象的更好语法


给出如下的 reducer 示例

_({
  expandAbility: (state, a: { which: string }) => ({
    ...state,
    report: state.report && {
      waitingForIt: false,
      content: state.report.content && {
        ...state.report.content,
        interaction: {
          expandAbilities: !state.report.content.interaction.expandAbilities.contains(a.which)
            ? state.report.content.interaction.expandAbilities.add(a.which)
            : state.report.content.interaction.expandAbilities.remove(a.which)
        }
      }
    }
  }),
})

(下面提供的州类型仅用于问题背景)

const initialState = {
  report: undefined as
    | {
        waitingForIt?: boolean
        content?: {
          supportedFightIds: number[]
          deathCut: number
          reportInfo: any
          deathsFull: any
          deathsByPlayer: any
          deathsByAbility: any
          interaction: {
            expandAbilities: Set<string>
          }
        }
      }
    | undefined,
  error: undefined as Error | undefined
}

有没有什么技巧或“时下流行”的库,可以让我用更简短的方式来写类似 expandAbility 的 reducer 更新操作?(除了可能创建一些 vars 来引用内部路径之外)

答案#1

有很多不可变更新的工具,您可以访问 https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md#immutable-update-utilities 查看一些选项,并看看哪个最适合您。作为起点,可以先看看 Immutability-helper 或 immer。

答案#2

所以你可以做两件事来帮助简化这个。第一件我喜欢做的事情是将逻辑移出 reducer,而只是传入一个值,并设置 expandAbilities 为 action.expandAbilities。

第二个实际上是我们在工作中做的事情。我们使用 immutableJS,并且编写了一个处理我们所有状态调用的单一 reducer,因为你可以给它一个需要更新的状态部分的路径以及要更新的值,所以我们把它提取出来了,现在很容易这样说 dispatch(actions.update({path: ['report', 'content', 'interaction', 'expandAbilities'], value: '123' }))

你甚至可以扩展这个功能,以便传入需要更新的值列表,甚至对数据进行验证。