Как добавить объект в индекс массива в редукторе

У меня есть магазин с массивами (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)}

Мне нужно добавить объект действия в индекс todos массива: Я пробовал с этим редуктором, но получаю ошибку:

state.calendar[newTodo.day].concat is not a function

Мой редуктор:

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;

Мои действия:

export const addTodoAction = (todoItem) => {
  return {
    type: ADD_TODO,
    todoItem
  }
}

Моя функция добавления todo:

const handleSaveTodo = () => {
    props.addTodo({ 
      day: 5,
      title: trackInput.value,
      description: trackTextarea.value,
      completed: false
    });
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
771
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вместо этого попробуйте state.calendar[newTodo.day].todo.concat(newTodo). Я думаю, вы пытаетесь использовать .concat() для объекта {todo: Array(0)}, а не для массива внутри.

вы можете попробовать это:

Редуктор:

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;
Ответ принят как подходящий

Вам нужно изменить свое состояние абсолютно неизменным образом.

Для этого вам нужно скопировать массив календаря, день, который вы обновляете в этом календаре, и список дел, к которому вы добавляете.

Сначала получите day и todoItem, вы можете использовать деструктурирование:

const { todoItem } = action;
const { day } = todoItem;

Затем скопируйте свой календарь, вы можете использовать для этого синтаксис распространения:

const calendar = [...state.calendar];

Затем обновите соответствующий день копией этого дня и добавьте новую задачу в список задач:

calendar[day] = { ...calendar[day], todos: [...calendar[day].todos, todoItem] };

Затем верните обновленное состояние:

return { ...state, calendar };

Вот пример:

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.info(state.calendar.slice(0, 3));

Другие вопросы по теме