Learn how to implement toggling a todo in a todo list application reducer.
Thanks for the videos Dan! Very informative and well structured. I try to write the tests first on my own before I watch you do it. Was surprised to see I came up with a solution different than yours. Want to post here for review to see if my solution misses edge cases or has performance issues. Relevant code below :
const todoReducer = (state = [], action) => {
switch (action.type) {
case "TOGGLE_TODO":
return [
...state.slice(0, action.id),
{...state[action.id], isCompleted: !state[action.id].isCompleted},
...state.slice(action.id + 1)
]
default:
return state;
}
}
thanks!
change the ids on the todos so they don’t follow a sequential pattern or match their position in the array.
Here's a way you could implement immutable updates in a reducer with Immutable.js:
const { List, Record } = Immutable;
const Todo = Record({
id: 0,
text: "",
completed: false
});
const todos = (state = List(), action) => {
switch (action.type) {
case "TOGGLE_TODO":
const index = state.findIndex(todo => todo.id === action.id);
return state.update(index, todo =>
todo.update("completed", completed => !completed)
);
default:
return state;
}
};
const testToggleTodo = () => {
const stateBefore = List([
Todo({
id: 0,
text: "Learn Redux",
completed: false
}),
Todo({
id: 1,
text: "Go shopping",
completed: false
})
]);
const action = {
type: "TOGGLE_TODO",
id: 1
};
const stateAfter = List([
Todo({
id: 0,
text: "Learn Redux",
completed: false
}),
Todo({
id: 1,
text: "Go shopping",
completed: true
})
]);
expect(todos(stateBefore, action)).toEqual(stateAfter);
};
testToggleTodo();
console.log("All tests passed.");
Because this code is looking up todos by id
, a better data structure to store Todo
s in may be an immutable Map
indexed by id
.
The toggle_todo
action could then be simplified to:
return state.update(action.id, todo =>
todo.update("completed", completed => !completed)
);