我试图切换数组中处于Redux状态的数组中的特定元素,然后使其反映使用该状态的组件中的更改。
我正在尝试将set中的完整状态更改为true,但是现在我的代码编写方式没有任何反应。
export const initialState: WorkoutList = {
workouts: [
{
id: "newId",
name: "Leg Day",
date: new Date(),
duration: 60,
started: false,
completed: false,
exercises: [
{
id: "e1",
name: "Squats",
completed: false,
sets: [
{
id: "e1s1",
reps: 12,
weight: 60,
completed: false,
},
{
id: "e1s2",
reps: 8,
weight: 60,
completed: false,
},
{
id: "e1s3",
reps: 10,
weight: 60,
completed: false,
},
],
},
{
id: "e2",
name: "Leg Press",
completed: false,
sets: [
{
id: "e2s1",
reps: 12,
weight: 60,
completed: false,
},
{
id: "e2s2",
reps: 8,
weight: 60,
completed: false,
},
{
id: "e2s3",
reps: 10,
weight: 60,
completed: false,
},
],
},
],
},
],
selectedWorkout: {
id: "newId",
name: "Leg Day",
date: new Date(),
duration: 60,
started: false,
completed: false,
exercises: [
{
id: "e1",
name: "Squats",
completed: false,
sets: [
{
id: "e1s1",
reps: 12,
weight: 60,
completed: false,
},
{
id: "e1s2",
reps: 8,
weight: 60,
completed: false,
},
{
id: "e1s3",
reps: 10,
weight: 60,
completed: false,
},
],
},
{
id: "e2",
name: "Leg Press",
completed: false,
sets: [
{
id: "e2s1",
reps: 12,
weight: 60,
completed: false,
},
{
id: "e2s2",
reps: 8,
weight: 60,
completed: false,
},
{
id: "e2s3",
reps: 10,
weight: 60,
completed: false,
},
],
},
],
},
selectedExercise: {
id: "e1",
name: "Squats",
completed: false,
sets: [
{
id: "e1s1",
reps: 12,
weight: 60,
completed: false,
},
{
id: "e1s2",
reps: 8,
weight: 60,
completed: false,
},
{
id: "e1s3",
reps: 10,
weight: 60,
completed: false,
},
],
},
};
const workoutListReducer = (
state = initialState,
action: WorkoutActionTypes
): WorkoutList => {
switch (action.type) {
case TOGGLE_SET_COMPLETE:
const updatedWorkoutState = state.workouts.map((workout) => {
if (workout.id === state.selectedWorkout?.id) {
workout.exercises?.map((exercise) => {
if (exercise.id === state.selectedExercise?.id) {
exercise.sets?.map((set) => {
if (set.id === action.payload.id) {
// console.log(set, !set.completed);
return { ...set, completed: true };
}
return set;
});
}
return exercise;
});
}
return workout;
});
const updatedSelectedWorkoutState = updatedWorkoutState.find(
(workout) => workout.id === state.selectedWorkout?.id
);
const updatedSelectedExerciseState = updatedSelectedWorkoutState?.exercises?.find(
(workout) => workout.id === state.selectedExercise?.id
);
console.log(updatedSelectedExerciseState);
return {
...state,
workouts: updatedWorkoutState,
selectedWorkout: updatedSelectedWorkoutState,
selectedExercise: updatedSelectedExerciseState,
};
default:
return state;
}
};
export default workoutListReducer;
答案 0 :(得分:0)
您的代码使用了返回值的map函数,但是,您的代码对此没有任何规定。此外,删除所有问号(?)。稍微修改一下代码,即可在下面看到一个可行的选择
...
// The initialState part of your code goes here
...
const workoutListReducer = (
state = initialState,
action: WorkoutActionTypes
): WorkoutList => {
switch (action.type) {
case TOGGLE_SET_COMPLETE:
// create a copy of workout state
const tempWorkoutState = [...state.workouts];
const updatedWorkoutState = tempWorkoutState.map((workout) => {
if (workout.id === state.selectedWorkout?.id) {
// Update workout.exercises with the result of the map function
workout.exercises = workout.exercises.map((exercise) => {
if (exercise.id === state.selectedExercise.id) {
// Update exercise.sets with the result of the map function
exercise.sets = exercise.sets.map((set) => {
if (set.id === action.payload.id) {
// console.log(set, !set.completed);
return { ...set, completed: true };
}
return set;
});
}
return exercise;
});
}
return workout;
});
const updatedSelectedWorkoutState = updatedWorkoutState.find(
(workout) => workout.id === state.selectedWorkout.id
);
const updatedSelectedExerciseState = updatedSelectedWorkoutState.exercises.find(
(workout) => workout.id === state.selectedExercise.id
);
console.log(updatedSelectedExerciseState);
return {
...state,
workouts: updatedWorkoutState,
selectedWorkout: updatedSelectedWorkoutState,
selectedExercise: updatedSelectedExerciseState,
};
default:
return state;
}
};
export default workoutListReducer;
答案 1 :(得分:0)
我认为问题在于您返回的是workout
对象的相同实例。您应该在workouts
中克隆“选定的锻炼”对象,以便react可以检测到某些更改。
map
函数有2种用法未正确应用。 map
应该用于生成由map
函数返回的新数组。但是在两种情况下,您使用map
忽略其结果。
您的代码应该做这样的事情(条件已经被反转以使问题代码更清晰):
const updatedWorkoutState = state.workouts.map((workout) => {
// Happy path, returns same instance
if (workout.id !== state.selectedWorkout?.id) {
return workout;
}
// Obtain the updated exercises for the selected workout
const updatedExercises = workout.exercises?.map((exercise) => {
// just return the exercise we don't care about as-is:
if (exercise.id !== state.selectedExercise?.id) {
return exercise;
}
// get the updated array of sets
const updatedExerciseSets = exercise.sets?.map((set) => {
if (set.id === action.payload.id) {
// console.log(set, !set.completed);
return { ...set, completed: true };
}
return set;
});
// Clone the selected exercise setting the updated array of sets:
return {
...exercise,
sets: updatedExerciseSets
};
});
// Now the selected workout should be cloned and its exercises array replaced
// with the updated one:
return {
...workout,
exercises: updatedExercises
};
});
这会使事情变得更加冗长,但是您可以使用一些库来帮助您解决诸如Immer
这样的不变性。