0

Fairly new with React and wanting to build a simple front end application (no database) with React.

The app is a trivia game and it involves creating "users" which involves a id #, name, a "answers" field to keep track of the answers they've provided and "points" which is an integer of 0 until the player answers a question correctly.

THE PROBLEM is creating a function to add +1 to the users 'answers'. Right now when I complete the function, it saves the state as a object and therefore gives my map() function errors.

My code:

import { Button } from "bootstrap";
import React, { Component, useState } from "react";
import { Header, Table } from "semantic-ui-react";
import NewPlayer from "./NewPlayer";
import DeletePlayer from "./DeletePlayer";

// STATE
class Trivia extends Component {
  constructor(props) {
    super(props);
    this.state = {
      players: [{ name: "PLAYER", id: 0, answers: 0, points: 0 }], // Need to change this
    };
    this.deletePlayer = this.deletePlayer.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.addPlayer = this.addPlayer.bind(this);
    this.answerYes = this.answerYes.bind(this);
  }

  // What I want it to do: onClick, add +1 to answers (eventually, add +1 to points)

  deletePlayer = (e, nid) => {
    e.preventDefault();
    var players = this.state.players;

    for (var i = 0; i < players.length; i++)
      if (players[i].id && players[i].id === nid) {
        players.splice(i, 1);
        break;
      }

    this.setState({ players: players });
  };

  addPlayer = (e) => {
    e.preventDefault();
    if (!this.state.newPlayerName) {
      return;
    }
    var currentPlayers = this.state.players;
    const lastID = currentPlayers[currentPlayers.length - 1];
    var variable = lastID.id + 1;
    const newPlayer = {
      name: this.state.newPlayerName,
      id: variable,
      answers: 0,
      points: 0,
    };
    this.setState({ players: [...this.state.players, newPlayer] });
    document.getElementById("name").value = "";
  };

  // FUNCTION THAT NEEDS HELP !!!
  answerYes = (e, id) => {
    // On click, answer goes up +1
    e.preventDefault();
    var players = this.state.players;
    this.setState({ players: this.state.players[id].answers + 1 });
  };

  answerNo = (e, id) => {
    e.preventDefault();
    // Subtract point away
  };
  handleChange(e) {
    this.setState({ newPlayerName: e.target.value });
  }

  render() {
    var { players } = this.state;
    console.log(players);

    return (
      <div>
        <Header as="h1">Players</Header>
        <Table>
          <thead>
            <tr>
              <th>Player #</th>
              <th>Name</th>
              <th>Answers</th>
              <th>Points</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {players.map((player) => {
              return (
                <tr>
                  <td>{player.id}</td>
                  <td>{player.name}</td>
                  <td>
                    {player.answers}
                    <button
                      onClick={(e) => {
                        this.answerYes(e, player.id);
                      }}
                    >
                      Correct
                    </button>
                    <button
                      onClick={(e) => {
                        this.answerNo(e, player.id);
                      }}
                    >
                      Incorrect
                    </button>{" "}
                  </td>
                  <td>{player.points}</td>
                  <td>
                    <button
                      onClick={(e) => {
                        this.deletePlayer(e, player.id);
                      }}
                    >
                      Delete
                    </button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </Table>
        <div>
          <form onSubmit={this.addPlayer}>
            <input
              type="text"
              value={this.state.name}
              id="name"
              placeholder="add 
                           player name...."
              onChange={this.handleChange}
            />

            <input type="submit" value="add player" />
          </form>
        </div>
      </div>
    );
  }
}

export default Trivia;

Right now the error I am getting is : Uncaught TypeError: players.map is not a function. I need help saving the state object. Thank you

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • `this.setState({players: this.state.players[id].answers + 1})` seems like it wouldn't result in something mappable. – Dave Newton May 10 '21 at 17:14
  • Does this answer your question? [How to update nested state properties in React](https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react) – Zachary Haber May 10 '21 at 17:14
  • Agreed, im still new to React to I am uncertain on how to properly edit + save the state nested object – SmoothOperator May 10 '21 at 17:15

1 Answers1

0

The problem is that you are trying to map var players which does not exist before clicking button

<button
  onClick={(e) => {
  this.answerYes(e, player.id);
  }}>

You should change the logic with your requirement flow or alternatively you can assign var player at first render in useEffect then can change in function

useEffect(() => {

var player = this.state.players
}, [] )
Evren
  • 4,147
  • 1
  • 9
  • 16
  • I should be implementing useEffect for my change button ? Im looking for any terms to help research a solution to this problem. Admittedly my current logic wont work with react and state – SmoothOperator May 10 '21 at 18:08