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

Hosung Kim
Hosung Kim
11,243 Points

Uncaught TypeError: props.removePlayer is not a function

Can someone help me figure out what is wrong with my code? I've watched the video multiple times, triple-checked my code, and I still can't seem to find what the issue is.

The React Dev Tools inspector declares the "removePlayer" function as "undefined" and upon invoking the function on clicking "X", I get an error in the console: Uncaught TypeError: props.removePlayer is not a function

const Header = (props) => {
  return (
    <header>
      <h1>{props.title}</h1>
      <span className="stats">Players: {props.totalPlayers}</span>
    </header>
  );
}

const Player = (props) => {
  return (
    <div className="player">
      <span className="player-name">
        <button className="remove-player" onClick={ () => props.removePlayer(props.id) }>✖</button>
        {props.name}  
      </span>

      <Counter />
    </div>
  );
}

class Counter extends React.Component {
  constructor() {
    super()
    this.state = {
      score: 0
    };
  }

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

  //You can use an arrow function to bind "this" which allows you to omit ".bind(this)" in the render method
  decrementScore = () => {
  //You can also wrap the object in parenthesis to omit the "return"
    this.setState( prevState => ({ 
      score: prevState.score - 1
    }));
  }

  handleRemovePlayer = (id) => {
    this.setState( prevState => {
      return {
        players: prevState.players.filter( p => p.id !== id )
      };
    });
  }

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

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      players: [
        {
          name: "Steven",
          id: 1
        },
        {
          name: "Treasure",
          id: 2
        },
        {
          name: "Ashley",
          id: 3
        },
        {
          name: "James",
          id: 4
        }
      ]
    };
  }

  render() {
    return (
      <div className="scoreboard">
        <Header 
          title="My Scoreboard" 
          totalPlayers={this.state.players.length} 
        />
        {/* Players List */}
        {this.state.players.map( player =>
          <Player 
            name={player.name}
            id={player.id}
            key={player.id.toString()}
            removePlayer={this.handleRemovePlayer}
          />
        )}
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')

2 Answers

Hi Hosung,

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      players: [
        {
          name: "Steven",
          id: 1
        },
        {
          name: "Treasure",
          id: 2
        },
        {
          name: "Ashley",
          id: 3
        },
        {
          name: "James",
          id: 4
        }
      ]
    };
  }

  render() {
    return (
      <div className="scoreboard">
        <Header 
          title="My Scoreboard" 
          totalPlayers={this.state.players.length} 
        />
        {/* Players List */}
        {this.state.players.map( player =>
          <Player 
            name={player.name}
            id={player.id}
            key={player.id.toString()}
            removePlayer={this.handleRemovePlayer}
          />
        )}
      </div>
    );
  }
}

From my understanding of react, you don't have the handleRemovePlayer function inside the App component. You're trying pass down a function that was created inside the counter component. Try moving the function to the App component and pass it down the children components.

Hosung Kim
Hosung Kim
11,243 Points

Eric Agbayani Ohhhh of course! Thanks so much!! Totally makes sense now. I appreciate it!