I can add 1 item to the array it logs [\"50\"] in the console. But when I try to add a second value I get this error \"currentScores.push is not a f
The problem is that push doesn't return a new array, bit the length of the amended array. So you're actually assigning state.stores to a number, which of course doesn't support push.
I can see you're trying to avoid mutating state by attempting to clone the scores array, but push will mutate it, not return a new instance. It might be better to do something like:
const newScores = [...this.state.scores, this.state.scoreInput];
this.setState({ scores: newScores });
The problem is over here
<button onClick={this.addScore(this.state.scoreInput)}>
add</button>);
When you run this.addScore(this.state.scoreInput)
inside the onclick, javascript runtime will call addScore function. Thats why you are getting 50~logs
Try <button onClick={ function(){this.addScore(this.state.scoreInput)}}>
add</button>);
The return value of currentScores.push()
is the new number of elements in the array. You then save this in your state which means that scores in your state becomes a number instead of an array.
You likely want to construct a new array instead since you are working with constant variables:
const currentScores = this.state.scores;
const newScores = currentScores.concat(this.state.scoreInput);
this.setState({ scores: newScores });
Two things, when you make use of push
it doesn't return a new array
. Make use of concat
and bind the value to the addUser function.
Also wrap your elements inside a single div and write your console.log()
statement to output the state value in the callback
function of setState since it takes some time to mutate
class Scores extends React.Component {
constructor() {
super();
this.addScore = this.addScore.bind(this);
this.handleScoreChange = this.handleScoreChange.bind(this);
this.state = {
scores: [],
scoreInput: '',
};
}
addScore() {
const currentScores = this.state.scores;
const newScores = currentScores.concat(this.state.scoreInput);
this.setState({ scores: newScores }, function(){
console.log(this.state.scores);
});
}
handleScoreChange(e) {
this.setState({ scoreInput: e.target.value });
}
render() {
const scores = this.state.scores;
return (
<div>
<input name="score" type="text" placeholder="Score" onChange={this.handleScoreChange}/>
<button onClick={this.addScore.bind(this, this.state.scoreInput)}>add</button></div>
);
}
}
ReactDOM.render(<Scores/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Push returns the new length property of the object upon which the method was called.
You set the state of scores to the new length each time.
addScore() {
console.log(this.state.scores);
this.setState(state=> ({
scores: [...state.scores, state.scoreInput]
})
);
}