Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

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

jobbol
seal-mask
.a{fill-rule:evenodd;}techdegree
jobbol
Full Stack JavaScript Techdegree Student 16,610 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.