Tengo un estado con la siguiente estructura. Contiene una lista de entrenamientos y cada entrenamiento tiene una lista de ejercicios relacionados con este entrenamiento. Quiero poder hacer 2 cosas:
Por ejemplo, en mi interfaz de usuario puedo agregar nuevos ejercicios a Entrenamiento con el nombre Day 2 . Entonces, mi carga útil de acción obtiene 2 parámetros: índice de entrenamiento (para que pueda encontrarlo más tarde en el estado) y ejercicio que debe agregarse o eliminarse de la lista de ejercicios del entrenamiento específico.
Estado
state = { workouts: [ { name: "Day 1", completed: false, exercises: [{ name: "push-up", completed: false }, { name: "running", completed: false }] }, { name: "Day 2", completed: false, exercises: [{ name: "push-up", completed: false }] }, { name: "Day 3", completed: false, exercises: [{ name: "running", completed: false }] }] }Comportamiento
export class AddExercise implements Action { readonly type = ADD_EXERCISE constructor(public payload: {index: number, exercise: Exercise}) {} } export class DeleteExercise implements Action { readonly type = DELETE_EXERCISE constructor(public payload: {index: number, exercise: Exercise}) {} }Y estoy atascado en el reductor. ¿Puede aconsejarme cómo se debe hacer correctamente? Así es como se ve en este momento (aún no finalizado):
reductor
export function workoutsReducer(state = initialState, action: WorkoutActions.Actions) { switch(action.type) { case WorkoutActions.ADD_EXERCISE: const workout = state.workouts[action.payload.index]; const updatedExercises = [ ...workout.exercises, action.payload.exercise ] return { ...state, workouts: [...state.workouts, ] } return {}; default: return state; } }¡Gracias!
Por favor, intente algo como lo siguiente (incluí comentarios dentro del código, espero que quede claro):
export function workoutsReducer(state = initialState, action: WorkoutActions.Actions) { switch(action.type) { case WorkoutActions.ADD_EXERCISE: // You can take advantage of the fact that array map receives // the index as the second argument // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map const workouts = state.workouts.map((workout, index) => { if (index != action.payload.index) { return workout; } // If it is the affected workout, add the new exercise const exercises = [ ...workout.exercises, action.payload.exercise ] return { ...workout, exercises } }) // return the updated state return { ...state, workouts } case WorkoutActions.DELETE_EXERCISE: // very similar to the previous use case const workouts = state.workouts.map((workout, index) => { if (index != action.payload.index) { return workout; } // the new exercises array will be composed by every previous // exercise except the provided one. I compared by name, // I don't know if it is accurate. Please, modify it as you need to const exercises = workout.exercises.filter((exercise) => exercise.name !== action.payload.exercise.name); return { ...workout, exercises } }) // return the new state return { ...state, workouts } default: return state; } }