JavaScript How to minimize reducers boilerplate when using redux with a POJO state?

I face difficulties to write reducers for Redux. Specifically I end up wrapping a lot of my state manipulation in .map, .slice etc. When the structure of my state object grows larger, the reducers become hard to read, with functions wrapping functions etc.

  • I didn't want to use Immutable.js as I wanted to stick to simple POJO as long as possible
  • I tried using combineReducers and reduceReducers libs, with are awesome. But often I end up requiring a large chunk of the state in my reducer.
  • I wrote a little utility, to help with creating a new state:
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);

It gives a new state, leaving the original state the same. The references of objects and arrays not modified stay the same (=== comparison is true).

Can someone tells me if I'm missing an easier way with es6 syntax to perform the same results? Or another better community maintained lib to get the same benefits?

Thanks for your time and expertise.

Answer:1

I suggest breaking your reducer up into smaller functions.

Below are four functions, each in turn deals with a smaller part of the state. (Though in each case the first parameter is called state, it's different every time). The action though, is always the same.

I haven't checked this code for correctness, but I hope you get the idea.

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;
}
Answer:2

I have a Rails 4.2 app that is getting requests from another domain. I'd like them to send a uuid that we set in our javascript. It works on localhost but not cross-domain. In our ...

I have a Rails 4.2 app that is getting requests from another domain. I'd like them to send a uuid that we set in our javascript. It works on localhost but not cross-domain. In our ...

  1. rails cross domain cookies
  2. rails cross domain
  3. rails allow cross domain requests
  4. rails api cross domain

I am retrieving a document from PouchDB in an Angular Service. The document is retrieved in the following format: { "_id":"segments", "_rev":"1-4f0ed65cde23fe724db13bea1ae3bb13", "segments":[ { "...

I am retrieving a document from PouchDB in an Angular Service. The document is retrieved in the following format: { "_id":"segments", "_rev":"1-4f0ed65cde23fe724db13bea1ae3bb13", "segments":[ { "...

  1. rxjs json array
  2. rxjs map json array

I'm having trouble figuring this out. I've created a table, and I want to use clickable buttons (not the arrow keys) to navigate through each cell and mark that cell as yellow. The table builds and I ...

I'm having trouble figuring this out. I've created a table, and I want to use clickable buttons (not the arrow keys) to navigate through each cell and mark that cell as yellow. The table builds and I ...

  1. javascript using buttons
  2. javascript using radio buttons
  3. javascript calculator using radio buttons
  4. calculator program in javascript using buttons

Currently I've got the following JSON feed: var data = { "feeds": { "regions": [{ "name": "Lichtenberg", "id": "01408.b", "suburbs": [{ "name": "Fennpfuhl", ...

Currently I've got the following JSON feed: var data = { "feeds": { "regions": [{ "name": "Lichtenberg", "id": "01408.b", "suburbs": [{ "name": "Fennpfuhl", ...

  1. creating array with for loop python
  2. creating array with values java
  3. creating array with numpy
  4. creating array with malloc
  5. creating array with new c++
  6. creating array with new
  7. creating array with negative size
  8. creating array with python
  9. creating array with
  10. creating array with integers java
  11. creating array with string
  12. creating array with mdadm
  13. creating array in java
  14. creating array in javascript
  15. creating array in php
  16. creating array in c
  17. creating array in matlab
  18. creating array in r
  19. creating array in js
  20. creating array in typescript