当使用具有POJO状态的redux时,如何最小化减速器样板?

时间:2015-11-03 00:06:20

标签: javascript reactjs redux

我为Redux编写Reducer会遇到困难。具体来说,我最终在.map,.slice等中包含了很多我的状态操作。当我的状态对象的结构变大时,reducers变得难以阅读,函数包含函数等。

  • 我不想使用Immutable.js,因为我想尽可能坚持简单的POJO
  • 我尝试使用combineReducersreduceReducers库,非常棒。但是我经常在减速机中要求大部分状态。
  • 我写了一个小实用程序,以帮助创建一个新状态:
var path = require('immutable-path').path;

let state = {
            level1: {
                level21: {
                    level3: 3
                },
                level22: [{
                    id: 1,
                    val: 1
                }, {
                    id: 2,
                    val: 2
                }]
            }
        };


  let newState = path(state, 'level1.level22[id=1].val', x => x + 10);

它给出一个新状态,使原始状态保持不变。未修改的对象和数组的引用保持不变(===比较为真)。

有人能告诉我,如果我错过了使用es6语法执行相同结果的更简单方法吗?或者另一个更好的社区维护lib以获得相同的好处?

感谢您的时间和专业知识。

2 个答案:

答案 0 :(得分:0)

我建议将你的减速机分解成更小的功能。

下面是四个函数,每个函数依次处理状态的一小部分。 (虽然在每种情况下第一个参数都称为状态,但每次都不同)。但是,行动始终是一样的。

我还没有检查此代码的正确性,但我希望你明白这一点。

function reducerTop(state, action) {
    switch (action.type) {
        case SET_VAL:
            return Object.assign({}, state, {
                [action.topLevel]: reducerNext(state[action.topLevel], action);
            });
    }
    return state;
}

function reducerNext(state, action) {
    switch (action.type) {
        case SET_VAL:
            return Object.assign({}, state, {
                [action.nextLevel]: reducerArray(state[action.nextLevel], action);
            });
    }
    return state;
}

function reducerArray(state, action) {
    switch (action.type) {
        case SET_VAL:
            const index = state.findIndex((item) => item.id === action.id);
            if (index > -1) {
                return [
                    ...state.slice(0, index),
                    reducerFinal(state[index], action),
                    ...state.slice(index + 1)
                ];
            }
    }
    return state;
}

function reducerFinal(state, action) {
    switch (action.type) {
        case SET_VAL:
            return Object.assign({}, state, {
                value: action.value
            });
    }
    return state;
}

答案 1 :(得分:0)

我认为这是redux本身的一个问题 - 它太低级了,有些东西(例如嵌套更新)应该更容易。此外,我相信将所有业务逻辑都放入动作创建者中是没有问题的,并且内部reducers只是更新我们的状态(并在需要时执行嵌套更新)。

从我的观点来看,另一个不必要的事情 - 常数。我们通常有一些所有redux实体的对象(例如,reducers),我认为它应该足以找出所有需要的常量。

有了这个想法,我编写了一个库redux-tiles,它完全正确 - 基于给定的类型,它创建常量,处理异步函数,并为您创建reducer。因此,典型的API请求如下所示:

import { createTile } from 'redux-tiles';
const requestTile = createTile({
  type: ['api', 'request'],
  fn: ({ api, params }) => api.get('/items', params),
});

它将创建所有常量,减速器,还可以处理故障,成功和加载状态。您可以使用redux-tiles here查看完整的HN API示例。您可能会发现嵌套,它将自动更新所有内容,您只需要返回一组值来嵌套。