Reputation: 748
I have store with arrays (store.calendar[0].todos[{title: title, etc...}]
)
0: {todos: Array(0)}
1: {todos: Array(0)}
2: {todos: Array(0)}
3: {todos: Array(0)}
4: {todos: Array(0)}
I need to add action object to the index todos of array: I have tried with this reducer, but I get an error:
state.calendar[newTodo.day].concat is not a function
My reducer:
let initialState = { calendar: []}
for (let i = 1; i <= 30; i++) {
initialState.calendar.push({ todos: []});
}
const todosReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
const newTodo = action.todoItem;
const newStore = {...state,
todos: state.calendar[newTodo.day].concat(newTodo)};
return newStore;
default:
return state
}
}
export default todosReducer;
My action:
export const addTodoAction = (todoItem) => {
return {
type: ADD_TODO,
todoItem
}
}
My add todo function:
const handleSaveTodo = () => {
props.addTodo({
day: 5,
title: trackInput.value,
description: trackTextarea.value,
completed: false
});
}
Upvotes: 2
Views: 1045
Reputation: 13964
You need to change your state in a totally immutable way.
For this, you have to copy the calendar array, the day you are updating in this calendar and the todo list you are appending to.
First get the day
and todoItem
, you can use destructuring:
const { todoItem } = action;
const { day } = todoItem;
Then copy your calendar, you can use the spread syntax for that:
const calendar = [...state.calendar];
Then update the relevant day with a copy for that day, and append the new todo to the list of todos:
calendar[day] = { ...calendar[day], todos: [...calendar[day].todos, todoItem] };
Then return the updated state:
return { ...state, calendar };
Here is an example:
const ADD_TODO = 'add-todo';
const initialState = { calendar: Array.from({ length: 30 }, (_, i) => ({ todos: [] })) };
const todosReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
const { todoItem } = action;
const { day } = todoItem;
const calendar = [...state.calendar];
calendar[day] = { ...calendar[day], todos: [...calendar[day].todos, todoItem] };
return { ...state, calendar };
default:
return state
}
}
let state = initialState;
state = todosReducer(state, { type: ADD_TODO, todoItem: { day: 0, title: 'todo day 1' } });
state = todosReducer(state, { type: ADD_TODO, todoItem: { day: 1, title: 'todo day 2' } });
state = todosReducer(state, { type: ADD_TODO, todoItem: { day: 2, title: 'todo day 3' } });
state = todosReducer(state, { type: ADD_TODO, todoItem: { day: 2, title: 'second todo day 3' } });
console.log(state.calendar.slice(0, 3));
Upvotes: 2
Reputation: 65
you could try this:
Reducer:
const initialState = {
calendar: Array.from({length: 30}, () => ({ todos: [] }))
}
const todosReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
const { todoItem } = action;
const newCalendar = [...state.calendar];
newCalendar[todoItem].todos.push(todoItem);
return {
...state,
calendar: newCalendar
}
default:
return state
}
}
export default todosReducer;
Upvotes: -1
Reputation: 470
Try state.calendar[newTodo.day].todo.concat(newTodo)
instead. I think you're trying to .concat() onto the object {todo: Array(0)} rather than the array within.
Upvotes: 0