I have pulled data from an api which has a list of exercises inside, here is an example exericse object.
{
pivot_id:1,
id:1,
image_path: "exercise\/images\/q3YaO7uuFYgZDFg7fnVpn3eYxrb5oUZeKwE6mNf7.png",
name:"Smitham PLC",
duration:423,
duration_per_rep:5,
intensity:{
id:2,
intensity: "Moderate Resistance Training",
met_value:4.5
},
image:"https:\/\/s3-eu-west-1.amazonaws.com\/fitness-concierge\/exercise\/images\/q3YaO7uuFYgZDFg7fnVpn3eYxrb5oUZeKwE6mNf7.png",
kcal:5,
},
I have created a customDuration state with a default value of 60, which I want to add to each exercise object by using a button to add a duration with an increment of 30 seconds. However, I am having an issue with updating just one specific item.
For example, I have two items rendered, and when I go to press the + button to add 30 seconds to the exercise it does, it goes from 60 - 90, but then when I go and add some time on the second item in the list it will go from 60 - 120 which is were the problem is occurring.
addDuration(item, index) {
let newArray = [...this.state.warm_up_exercises];
newArray[index] = {
...newArray[index],
customDuration: this.state.customDuration = this.state.customDuration + 30,
storeValues: true,
workoutStoreType: 'duration',
};
this.setState({
warm_up_exercises: newArray,
});
}
Above is the function I am using to add a duration to the exercise, I have tried to do item.customDuration = item.customDuration + 30 but I just get NaN in the console.
In my mapping function I have the custom duration showing like this
<Text>{{ item.customDuration }}</Text>
I've been struggling with this a couple of days now so much help would be really appreciated. All I am trying to achieve is to just make it so when I add the values to the array, it will update that item and have no effect on the other items.
Additional Code to provide more context:
My constructor:
constructor(props) {
super(props) {
warm_up_exercises: [],
selected_warm_up_exercises: [],
repsValue: 0,
setsValue: 0,
restValue: 0,
workoutStoreType: "",
customDuration: 60,
}
}
Were I call the function:
<TouchableOpacity onPress={() => this.addDuration(item, index)}>
<AntDesign name="pluscircle" size={22} color={Colours.type.primary_colour} />
</TouchableOpacity>
First, you are not properly initialising your state. It should be an object, which has the exercise array as a property. Write it like this:
constructor(props) {
super(props) {
this.state = {
exercises: [],
repsValue: 0,
setsValue: 0,
restValue: 0,
workoutStoreType: "",
customDuration: 60,
}
}
}
Every time you increment the state you are not just mutating it, but you also put customDuration to every entity. The problem lies here:
customDuration: this.state.customDuration = this.state.customDuration + 30
In order to do it right, you just need to write:
customDuration: this.state.customDuration + 30
And then, to increment the state you should do it separately :
this.setState({
exercises: newArray,
customDuration: this.state.customDuration + 30
});
In case you need to have a customDuration to every item you also need to change the state in the same way, but with a bit of a twist:
addDuration(item, index) {
let newArray = [...this.state.exercises]
newArray[index] = {
...newArray[index],
customDuration: newArray[index].customDuration ? newArray[index].customDuration + 30 : 90,
storeValues: true,
workoutStoreType: 'duration',
};
this.setState({
exercises: newArray,
});
}
And then remove customDuration from the initial state. This way you will increment by 30 and put 90 the first time you increment