Pushing data pushes twice to array
Answered
German yellowjacket posted this in #help-forum
German yellowjacketOP
I have this data structure
and i when i press this button
it runs this
but it appends 2 sets to the exercise instead of one. Not sure
let sampleWorkoutData: WorkoutData = {
workoutName: 'Chest Day',
notes: 'This is a sample workout for chest day',
exercises: [
{
exerciseName: 'Dumbbell Flys',
sets: [
{
setNumber: 1,
reps: 10,
weight: 20
},
{
setNumber: 2,
reps: 8,
weight: 25
},
{
setNumber: 3,
reps: 6,
weight: 30
}
]
}
]
}
and i when i press this button
<Button variant="link" onClick={() => addSet(exerciseIndex)}>Add Set</Button>
it runs this
const [exercises, setExercises] = useState(workoutData.exercises);
const isAddingSet = useRef(false);
const addSet = (exerciseIndex) => {
if (isAddingSet.current) return;
isAddingSet.current = true;
setExercises(prevExercises => {
const updatedExercises = [...prevExercises];
updatedExercises[exerciseIndex].sets.push({
setNumber: updatedExercises[exerciseIndex].sets.length + 1,
reps: 0,
weight: 0,
});
return updatedExercises;
});
setTimeout(() => {
isAddingSet.current = false;
});
};
but it appends 2 sets to the exercise instead of one. Not sure
6 Replies
German yellowjacketOP
the full code is here
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import React, { useState, useRef } from 'react';
function WorkoutDetails({ workoutData }) {
const [exercises, setExercises] = useState(workoutData.exercises);
const isAddingSet = useRef(false);
const addSet = (exerciseIndex) => {
if (isAddingSet.current) return;
isAddingSet.current = true;
setExercises(prevExercises => {
const updatedExercises = [...prevExercises];
updatedExercises[exerciseIndex].sets.push({
setNumber: updatedExercises[exerciseIndex].sets.length + 1,
reps: 0,
weight: 0,
});
return updatedExercises;
});
setTimeout(() => {
isAddingSet.current = false;
});
};
return (
<div>
<h2>Workout: {workoutData.workoutName}</h2>
<p>Notes: {workoutData.notes}</p>
<div>
{exercises.map((exercise, exerciseIndex) => (
<div key={exerciseIndex}>
<h3>Exercise: {exercise.exerciseName}</h3>
<ul>
{exercise.sets.map((set, setIndex) => (
<li key={setIndex}>
Set {set.setNumber}: {set.reps} reps, {set.weight} lbs
</li>
))}
</ul>
<Separator />
<Button variant="link" onClick={() => addSet(exerciseIndex)}>Add Set</Button>
</div>
))}
</div>
</div>
);
}
export default WorkoutDetails;
this comment should explain what is happening. You are in dev, so mostly its the strict mode coz the code looks correct otherwise
actually this will be more clear from official docs
https://arc.net/l/quote/iqulaged
https://arc.net/l/quote/iqulaged
setExercises(prevExercises => {
const updatedExercises = [...prevExercises];
updatedExercises[exerciseIndex].sets.push({
setNumber: updatedExercises[exerciseIndex].sets.length + 1,
reps: 0,
weight: 0,
});
return updatedExercises;
});
This is causing the code to runs twce. Dont put side effects inside a setter.