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 React Basics (retired) Stateful Components Updating State

Xiaoxuan Wang
Xiaoxuan Wang
4,590 Points

Getting 'Uncaught TypeError: Cannot read property 'initialScore' of undefined'

Please check my code below:

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

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

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


class Counter extends React.Component {

constructor() {
    super();

    this.state = this.props.initialScore;
    this.incrementScore = this.incrementScore.bind(this);
    this.decrementScore = this.decrementScore.bind(this);
  }

incrementScore(){ 
    this.setState((prevState) => ({
    score: prevState.score + 1
   }))};


decrementScore(){ 
    this.setState((prevState) => ({
    score: prevState.score - 1
   }))};


render() {
    return <div className="counter">
      <button className="counter-action decrement" onClick = {this.decrementScore}> - </button>
      <div className="counter-score"> {this.state.score} </div>
      <button className="counter-action increment" onClick = {this.incrementScore}> + </button>
    </div>;
  }
}

Counter.propTypes ={
  initialScore: React.PropTypes.number.isRequired,
};

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

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

function Application(props) {
  return (
    <div className="scoreboard">
      <Header title={props.title} />

      <div className="players">
        {props.players.map(function(player) {
          return <Player name={player.name} score={player.score} key={player.id} />
        })}
      </div>
    </div>
  );
}

Application.propTypes = {
  title: React.PropTypes.string,
  players: React.PropTypes.arrayOf(React.PropTypes.shape({
    name: React.PropTypes.string.isRequired,
    score: React.PropTypes.number.isRequired,
    id: React.PropTypes.number.isRequired,
  })).isRequired,
};

Application.defaultProps = {
  title: "Scoreboard",
}

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

I'm using ES6 syntax code the example in the video, everything went well before adding the 'intialScore' property.

I got an error:Uncaught TypeError: Cannot read property 'initialScore' of undefined.

Can somebody help me with it?

Thanks,

1 Answer

Chris Shaw
Chris Shaw
26,676 Points

Hi Xiaoxuan Wang,

You have a couple of small mistakes. The first of the two is you are trying to access your props via this which won't work as the base class doesn't set this property until after your constructor is called. To get around this, React passes the props object as the first argument of our constructor method.

The second mistake you have is you're attempting to directly set initialScore on your components state which won't work as later on you're trying to access it via a property called score within state. Instead, your initial state should have this property and you should be assigning the value to it.

Please see the below:

class Counter extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      score: props.initialScore
    };

    this.incrementScore = this.incrementScore.bind(this);
    this.decrementScore = this.decrementScore.bind(this);
  }

  // Rest of your React component...
}

As you can see as per what I mentioned above, we are now accessing the initialScore correctly using the props parameter that is passed to our constructor, and then assigning it to a property within state called score.

Happy coding!

Xiaoxuan Wang
Xiaoxuan Wang
4,590 Points

Thanks Chris, that is really helpful, thank you for your time.