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: Arra...

问题:

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

回答1:

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


回答2:

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.


回答3:

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;

  • 发表于 2019-03-22 00:40
  • 阅读 ( 187 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除