Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript

can't add new player to array players Cannot add new players - page refreshes and I lose the newly added player

var PLAYERS = [
  {
    name: "Jim Hoskins",
    score: 31,
    id: 1,
  },
  {
    name: "Andrew Chalkley",
    score: 35,
    id: 2,
  },
  {
    name: "Alena Holligan",
    score: 42,
    id: 3,
  },
];

  var nextId = 4;


var AddPlayerForm = React.createClass({
  propTypes: {
    onAdd: React.PropTypes.func.isRequired,
  },

  getInitialState: function() {
    return {
      name: "",
    };
  },

  onNameChange: function(e)  {
    //console.log('onNameChange', e.target.value);
    //update name to e.target.value

    this.setState({name: e.target.value});  
  //every time i type update state - which will cause a re-render

  },

  onSubmit: function(e) {
    e.preventDefault;   //prevent from resubmitting to itself

    //pass the name up to the application 
    this.props.onAdd(this.state.name);

    //on submit, clear out name 
    this.setState({ name: "" });

  },
   render: function() {
    return (
      <div className="add-player-form">
        <form onSubmit={this.onSubmit}> 
          <input type="text"  value={this.state.name} onChange={this.onNameChange}/>
          <input type="submit" value="Add Player" />
        </form>
      </div>
    );
  }
  });


function Stats(props) {

  var totalPlayers = props.players.length; 
  var totalPoints = props.players.reduce(function(total, player){
  return total + player.score;
  }, 0)

  return (
    <table className="stats">
      <tbody>
        <tr> 
          <td> 
            Players
          </td>
          <td> 
           {totalPlayers}
          </td>
        </tr>
        <tr> 
          <td> 
            Total Points
          </td>
          <td> 
           {totalPoints}
          </td>
        </tr>
      </tbody>
    </table>
  );

  }


  Stats.propTypes = {
    players: React.PropTypes.array.isRequired,
  };



  function Header(props) {
  return (
    <div className="header">
      <Stats players={props.players} />
      <h1>{props.title}</h1>
    </div>
  );
}

Header.propTypes = {
  title: React.PropTypes.string.isRequired,
  players: React.PropTypes.array.isRequired,
};



  function Counter (props) {
    return (
      <div className="counter">
        <button className="counter-action decrement" onClick ={ function() {props.onChange(-1);} } > - </button>
        <div className="counter-score"> {props.score} </div>
        <button className="counter-action increment" onClick ={ function() {props.onChange(+1);} }> + </button>
      </div>
    ); 
  }

   Counter.propTypes = {
    score: React.PropTypes.number.isRequired,
    onChange: React.PropTypes.func.isRequired,
  }




function Player(props) {
  return (
    <div className="player">
      <div className="player-name">
        {props.name}
      </div>
      <div className="player-score">
        <Counter score={props.score} onChange={props.onScoreChange} />
      </div>
    </div>
  );
}

Player.propTypes = {
  name: React.PropTypes.string.isRequired,
  score: React.PropTypes.number.isRequired,
  onScoreChange: React.PropTypes.func.isRequired,
};


  /* Application holds state since players can change over time 
  can change state from application and cascade that state 
  down to Player and Counter 
  */

var Application = React.createClass({

  propTypes: {
     title: React.PropTypes.string,
      initialPlayers: React.PropTypes.arrayOf(React.PropTypes.shape({
    name: React.PropTypes.string.isRequired,
    score: React.PropTypes.number.isRequired,
    id: React.PropTypes.number.isRequired,
  })).isRequired,
  },

  //return object for default props 
  getDefaultProps: function() {
  return {
    title: "Scoreboard",
    }
  },

  //return initial state for Players since can change # of players and number of players 
  getInitialState: function() {
    return{
      players: this.props.initialPlayers,
    }
  },

  onScoreChange: function(index, delta) {
    console.log("onScoreChange", index, delta);
    this.state.players[index].score += delta;
    this.setState(this.state);
  },

  onPlayerAdd: function(name) {
    //console.log("player added", name);
    //add player to state
    this.state.players.push({
      name: name,
      score: 0,
      id: nextId,
    });
    this.setState(this.state);
    nextId += 1;

  },

  render: function() {
    return (
    <div className="scoreboard">
      <Header title={this.props.title} players={this.state.players} />

      <div className="players">
        {this.state.players.map(function(player, index) {
          return (
            <Player 
                onScoreChange={
  function(delta){this.onScoreChange(index, delta)}.bind(this)}
                name={player.name} 
                score={player.score} 
                key={player.id} /> 
   );
        }.bind(this))}
      </div>
      <AddPlayerForm onAdd={this.onPlayerAdd} />
    </div>
    );
  }
});  





ReactDOM.render(<Application initialPlayers={PLAYERS}/>, document.getElementById('container'));

e.preventDefault should have parentheses

e.preventDefault();

1 Answer

Josh Olson
Josh Olson
13,236 Points

Your page refreshes because it's apart of the default feature when submitting a form.

Inside the onSubmit your preventDefault function is referenced instead of called. You have:

e.preventDefault;

You want

e.preventDefault();

thank Ashish and Josh.