0

I'm trying to follow todo-app with react. I am writing "update all as completed" function, in flux.

while in redux todomvc example, todos are array

state = [{id: 1, text: "Read flux", completed: false}, ...]

so they use this method

const areAllMarked = state.every(todo => todo.completed)
return state.map(todo => Object.assign({}, todo, {
    completed: !areAllMarked
}))

https://github.com/reactjs/redux/blob/master/examples/todomvc/reducers/todos.js

but i am using todos as a Object like {id: todo}

state = {1: {text: "Read flux", completed: false}, ...}

then, is there any proper, functional way to get updated object with Object.assign?

FourwingsY
  • 669
  • 2
  • 7
  • 18

2 Answers2

0

I use a cool immutability helper library called timm.

Really helpful in doing the non-mutation based updates without having to change too much in your code (like when using Immutable.js). It does the job fast and well.

Here is an implementation using your code example:

import timm from 'timm'; 

const updatedState = timm.setIn(state, ['1', 'completed'], true);

Immutability.js is far stronger, and often gets recommended as the de facto library for immutability in JS, but it is a pretty heft library and makes you access your objects/array in a non-native manner so you lose cool things like destructuring.

I am not knocking Immutability.js, in my opinion it is probably the strongest in the market, however sometimes you don't need a full blown chainsaw when a simple knife will do. Start with something that has low friction and cost and work your way up the stack as and when you identify a problem that a stronger tool would solve.

ctrlplusb
  • 12,847
  • 6
  • 55
  • 57
0

I would recommend the object spread operator. This is part of ES7 specification, so make sure to have the respective babel plugin installed. This code makes use of the spread operator and calls a nested todo reducer, which is in charge of changing single todos (code from Dan Abramovs egghead tutorial):

const byId = (state = {}, action) => {
  switch (action.type) {
    case 'ADD_TODO':
    case 'TOGGLE_TODO':
      return {
        ...state,
        [action.id]: todo(state[action.id], action),
      };
    default:
      return state;
  }
};

The nested reducer could look like:

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        id: action.id,
        text: action.text,
        completed: false,
      };
    case 'TOGGLE_TODO':
      if (state.id !== action.id) {
        return state;
      }
      return {
        ...state,
        completed: !state.completed,
      };
    default:
      return state;
  }
};
FlorianE
  • 96
  • 1
  • 6
  • 3
    It's not actually a part of the spec. It's in proposal phase (stage 2). https://github.com/sebmarkbage/ecmascript-rest-spread – ctrlplusb Jun 07 '16 at 08:17