Reputation: 25
I'm trying to create a simple component that will act as a counter! There are two counters, one for counting repetitions, and another for counting amounts lifted. For some reason, the functions that I write are not working as intended.
The expected result is, when I click on the up or down arrow for say, reps, it should update THAT number in the state. Same goes for the amount lifted.
But what's happening is, when I click the up and down arrow for let's say, reps again, it works and increments and decrements correctly, but when I then click the arrows to increment and decrement the amount lifted, NaN is returned and then if I click on the rep arrows after that, that too then returns NaN.
Here's my relevant code:
class TrackProgress extends Component {
constructor(props) {
super(props);
this.state = {
id: parseInt(this.props.match.params.id),
exercise: [],
trackProgress: {
exercise_id: parseInt(this.props.match.params.id),
date: "",
reps: 0,
amountLifted: 0
}
};
}
handleChanges = e => {
this.setState({
trackProgress: {
...this.state.trackProgress,
[e.target.name]: e.target.value
}
});
};
repsIncrease = () => {
this.setState({
trackProgress: {
reps: this.state.trackProgress.reps + 1
}
});
};
repsDecrease = () => {
this.setState({
trackProgress: {
reps: this.state.trackProgress.reps - 1
}
});
};
amountLiftedIncrease = () => {
this.setState({
trackProgress: {
amountLifted: this.state.trackProgress.amountLifted + 1
}
});
};
amountLiftedDecrease = () => {
this.setState({
trackProgress: {
amountLifted: this.state.trackProgress.amountLifted - 1
}
});
};
render() {
return (
<div className="track-progress-container">
<div className="track-progress-content">
<div className="heading">
<h1>Start Tracking</h1>
<h2>{this.state.exercise.exerciseTitle}</h2>
</div>
<form className="tracking-form-container" onSubmit={this.onSubmit}>
<div className="rep-lift-flex">
<div>
<h6>REPS</h6>
<input
name="reps"
type="text"
placeholder="OO"
value={this.state.trackProgress.reps}
onChange={this.handleChanges}
/>
</div>
<div>
<h6>LIFTED</h6>
<input
name="amountLifted"
type="text"
placeholder="OO"
value={this.state.trackProgress.amountLifted}
onChange={this.handleChanges}
/>
</div>
</div>
<div className="arrow-container">
<div className="rep-arrows">
<img
src={down}
alt="decrease"
name="decrementReps"
className={
this.state.trackProgress.reps === 0 ? "inactive" : ""
}
onClick={this.repsDecrease}
/>
<img
src={up}
alt="increase"
name="incrementReps"
onClick={this.repsIncrease}
/>
</div>
<div className="lift-arrows">
<img
src={down}
alt="decrease"
name="decrementLifted"
onClick={this.amountLiftedDecrease}
className={
this.state.trackProgress.amountLifted === 0
? "inactive"
: ""
}
/>
<img
src={up}
alt="increase"
name="incrementLifted"
onClick={this.amountLiftedIncrease}
/>
</div>
</div>
<h6>Date</h6>
<input
name="date"
type="date"
placeholder="e.g. June 11, 2019"
value={this.state.trackProgress.date}
onChange={this.handleChanges}
className="date"
/>
<button type="submit" className="track-btn">
TRACK EXERCISE
</button>
</form>
</div>
</div>
);
}
}
export default TrackProgress;
Here's were my initial functions before I wrote out more specific function. They both produced the same results.
reps = event => {
if (event.target.name === "incrementReps") {
this.setState({
trackProgress: {
reps: this.state.trackProgress.reps + 1
}
});
} else if (event.target.name === "decrementReps") {
this.setState({
trackProgress: {
reps: this.state.trackProgress.reps - 1
}
});
}
};
amountLifted = event => {
if (event.target.name === "incrementLifted") {
this.setState({
trackProgress: {
amountLifted: this.state.trackProgress.amountLifted + 1
}
});
} else if (event.target.name === "decrementLifted") {
this.setState({
trackProgress: {
amountLifted: this.state.trackProgress.amountLifted - 1
}
});
}
};
I could be missing crucial logic or not account for something, I've been staring at this for hours, so help solving this would be greatly appreciated! Thank you!!
Upvotes: 1
Views: 93
Reputation: 2890
You are replacing the whole trackProgress object when you update either reps or amount lifted. Your state is:
this.state = {
id: parseInt(this.props.match.params.id),
exercise: [],
trackProgress: {
exercise_id: parseInt(this.props.match.params.id),
date: "",
reps: 0,
amountLifted: 0
}
}
Calling your update function for reps or currently replaces the entire trackProgress object, instead of just updating the properties you want.
repsIncrease = () => {
this.setState({
trackProgress: {
reps: this.state.trackProgress.reps + 1
}
});
};
Leads to:
state = {
id: 1,
exercise: [],
trackProgress: {
reps: 1,
}
}
To fix this, you can include all the previous properties in your repsIncrease/decrease function, or use the spread operator to automatically fill them out. Here's an example of the fixed repsIncrease function.
repsIncrease = () => {
this.setState({
trackProgress: {
...this.state.trackProgress,
reps: this.state.trackProgress.reps + 1
}
});
};
Upvotes: 2