4

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 function". Is this the wrong way of doing it?

 class Scores extends 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.push(this.state.scoreInput);
        this.setState({ scores: newScores });
        console.log(this.state.scores);
      }

      handleScoreChange(e) {
        this.setState({ scoreInput: e.target.value });
      }

      render() {
        const scores = this.state.scores;
        return (
                <input name="score" type="text" placeholder="Score" onChange={this.handleScoreChange}/>
                <button onClick={this.addScore(this.state.scoreInput)}>add</button>
        );
      }
    }

    export default Scores;

5 Answers 5

3

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>

Sign up to request clarification or add additional context in comments.

Comments

2

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 });

1 Comment

How can I return an array in this situation?
1

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]
            })
         );
      }

Comments

0

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 });

Comments

0

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>);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.