简体   繁体   中英

How to add object at array index in reducer

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
    });
}

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)); 

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.

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; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM