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 Building Applications with React and Redux Putting it all Together Updating the Player, Counter and AddPlayerForm Components

benjaminmosery
benjaminmosery
6,346 Points

Scoreboard not displaying properly

My Scoreboard is running, but it is not displaying properly: 1) I see only an "S" for the player name. 2)The remove player, increase/decrease player score, stopwatch start/stop buttons, and the Add Player Form are all present but do not seem to be working. I believe that something may be wrong with my Bound Action Creators. Can someone take a look? Any help would be appreciated. Here is what I have in my Scoreboard.js file (in the containers folder):

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {bindActionCreators} from 'redux';
import * as PlayerActionCreators from '../actions/Player';
import {connect} from 'react-redux';
import Player from '../components/Player';
import Header from '../components/Header';
import AddPlayerForm from '../components/AddPlayerForm';


class Scoreboard extends Component {
  static propTypes = {
    players: PropTypes.array.isRequired
  };


  render() {
const {dispatch, players} = this.props;
const AddPlayer = bindActionCreators(PlayerActionCreators.AddPlayer, dispatch);
const RemovePlayer = bindActionCreators(PlayerActionCreators.RemovePlayer, dispatch);
const UpdatePlayerScore =  bindActionCreators(PlayerActionCreators.UpdatePlayerScore, dispatch);

const PlayerComponents = players.map((player, index) => {
return (
  <Player
    index = {index}
    name = {Player.name}
    score = {Player.score}
    key = {Player.name}
    UpdatePlayerScore = {UpdatePlayerScore}
    RemovePlayer = {RemovePlayer}
/>
)
});

Please notify me if any more information is needed to resolve this issue Thanks in advance.

Steven Parker
Steven Parker
218,829 Points

Since this code relies on other components, you might want to make a snapshot of your workspace and post the link to it here.

If you weren't using one already you might consider importing the project into one for the purpose of facilitating analysis.

benjaminmosery
benjaminmosery
6,346 Points

I cant preview my workspace as I used Atom to create the application. Here are my components: AddPlayerForm.js:

import React, { Component} from 'react';
import PropTypes from 'prop-types';

export default class AddPlayerForm extends Component {
  static propTypes: {
    AddPlayer: PropTypes.func.isRequired
  };

  state = {
    name: ''
  };

  onNameChange = (e) => {
    const name = e.target.value;
    this.setState({ name: name });
  };

  AddPlayer = (e) => {
    if (e) e.preventDefault();
    this.props.AddPlayer(this.state.name);
    this.setState({ name: '' });
  };

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

Counter.js:

import React from 'react';
import PropTypes from 'prop-types';

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

Counter.propTypes = {
  UpdatePlayerScore: PropTypes.func.isRequired,
  score: PropTypes.number.isRequired,
  index: PropTypes.number.isRequired
};

export default Counter;

Header.js:

import React from 'react';
import Stats from './Stats';
import Stopwatch from './Stopwatch';
import PropTypes from 'prop-types';

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

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

export default Header;

Player.js:

import React from 'react';
import Counter from './Counter';
import PropTypes from 'prop-types';

const Player = props => {
  return (
    <div className="player">
      <div className="player-name">
        <a className="remove-player" onClick={() => props.RemovePlayer(props.index)}>✖</a>
        {props.name}
      </div>
      <div className="player-score">
        <Counter
         index = {props.index}
         UpdatePlayerScore={props.UpdatePlayerScore}
         score={props.score} />
      </div>
    </div>
  );
}

Player.propTypes = {
  name: PropTypes.string.isRequired,
  score: PropTypes.number.isRequired,
  index: PropTypes.number.isRequired,
  RemovePlayer:PropTypes.func.isRequired,
  UpdatePlayerScore:PropTypes.func.isRequired
};

export default Player;

Stats.js:

import React from 'react';
import PropTypes from 'prop-types';

const Stats = props => {
  const playerCount = props.players.length;
  const totalPoints = props.players.reduce(function(total, player) {
    return total + player.score;
  }, 0);

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

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

export default Stats;

Stopwatch.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Stopwatch extends Component {
  state = {
    running: false,
    previouseTime: 0,
    elapsedTime: 0,
  };

  componentDidMount() {
    this.interval = setInterval(this.onTick);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  onStart = () => {
    this.setState({
      running: true,
      previousTime: Date.now(),
    });
  };

  onStop = () => {
    this.setState({
      running: false,
    });
  };

  onReset = () => {
    this.setState({
      elapsedTime: 0,
      previousTime: Date.now(),
    });
  };

  onTick = () => {
    if (this.state.running) {
      var now = Date.now();
      this.setState({
        elapsedTime: this.state.elapsedTime + (now - this.state.previousTime),
        previousTime: Date.now(),
      });
    }
  };

  render() {
    var seconds = Math.floor(this.state.elapsedTime / 1000);
    return (
      <div className="stopwatch" >
        <h2>Stopwatch</h2>
        <div className="stopwatch-time"> {seconds} </div>
        { this.state.running ?
          <button onClick={this.onStop}>Stop</button>
          :
          <button onClick={this.onStart}>Start</button>
        }
        <button onClick={this.onReset}>Reset</button>
      </div>
    )
  }
}

I hope this helps. Please let me know if anything else is needed.