0
votes

I wrote a BlackJack game, however after I query API from deck of cards API, the cards never showed on the screen. I have console log'd the player deck and deal deck, it has the card data but nothing displayed.

heres the error: index.js:1375 Warning: Each child in a list should have a unique "key" prop.

Check the render method of BlackJack. See https://reactjs.org/link/warning-keys for more information. at div at BlackJack (http://localhost:3000/static/js/main.chunk.js:4166:3) at WithStyles(BlackJack) (http://localhost:3000/static/js/0.chunk.js:54861:31)

this is the data after query

[Array(2)]
0: Array(2)
0: {code: "6C", image: "https://deckofcardsapi.com/static/img/6C.png", images: {…}, value: "6", suit: "CLUBS"}
1: {code: "JD", image: "https://deckofcardsapi.com/static/img/JD.png", images: {…}, value: "JACK", suit: "DIAMONDS"}
length: 2
__proto__: Array(0)
length: 1
__proto__: Array(0)

[Array(1)]
0: Array(1)
0: {code: "4H", image: "https://deckofcardsapi.com/static/img/4H.png", images: {…}, value: "4", suit: "HEARTS"}
length: 1
__proto__: Array(0)
length: 1
__proto__: Array(0)

below is my code:

import React, { useState, useEffect, useCallback } from 'react';
import axios from 'axios';
import { withStyles } from '@material-ui/core/styles';

const styles = () => ({
  app: {
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    flexDirection: 'column'
  },
  deckContainer: {
    textAlign: 'center'
  }
})

const BlackJack = ({ classes }) => {
  const [deckId, setDeckId] = useState(null);
  const [playerDeck, setPlayerDeck] = useState([]);
  const [dealerDeck, setDealerDeck] = useState([]);
  const [gameOver, setGameOver] = useState(false);
  const [winner, setWinner] = useState(null);

  useEffect(async () => {
    const deck_id = await axios.get('https://deckofcardsapi.com/api/deck/new/shuffle/?deck_count=1')
      .then(res => res.data.deck_id);
    setDeckId(deck_id);
  }, []);

  const handleStartGame = async () => {

    const playerDeckList = [];
    const dealerDeckList = [];
    const playerDrawnCards = await axios.get(`https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=2`).then(res => res.data.cards);
    playerDeckList.push(playerDrawnCards);
    setPlayerDeck(playerDeckList);

    const dealerDrawnCards = await axios.get(`https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=1`).then(res => res.data.cards);
    dealerDeckList.push(dealerDrawnCards);
    setDealerDeck(dealerDeckList);
  };
  console.log(deckId);
  console.log(playerDeck);
  console.log(dealerDeck);
  // console.log(playerDeck[0]);


  return (
    <div className={classes.app}>
      <h1>Welcome to the Black Jack Game</h1>
      <br />
      <div>
        <button onClick={handleStartGame}>start game</button>
        {/* <button onClick={handlePlayerHit}>hit</button> */}
        {/* <button onClick={handlePlayerStand}>stand</button> */}
        {/* <button onClick={handlePlayerReset}>reset game</button> */}
      </div>
      <div>
        {/* <GameOver isGameOver={gameOver} /> */}
      </div>
      <br />
      <div>
        <h2>Dealer: </h2>
        <div className={classes.deckContainer}>
          {dealerDeck.map(card => {
            return (
              <div key={card.code}>
                <img
                  src={card.image}
                  alt={card.value}
                />
              </div>
            )
          })}
        </div>
        <br />
        <h2>Player: </h2>
        <div className={classes.deckContainer}>
          {playerDeck.map(card => {
            return (
              <div key={card.code}>
                <img
                  src={card.image}
                  alt={card.value}
                />
              </div>
            )
          })}
        </div>
      </div>
    </div>
  )
};

export default withStyles(styles)(BlackJack);

2

2 Answers

0
votes

The data you are setting is an array of an array, because res.data.cards is already an array.

So change your handleStartGame to

  const handleStartGame = async () => {
    const playerDrawnCards = await axios
      .get(`https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=2`)
      .then((res) => res.data.cards);
    setPlayerDeck(playerDrawnCards);

    const dealerDrawnCards = await axios
      .get(`https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=1`)
      .then((res) => res.data.cards);
    setDealerDeck(dealerDrawnCards);
  };
-1
votes

That's probably because fetching api is async operation. React first renders your jsx then go through the logic, at the moment your dealerdeck is getting mapped empty. Try setting up 1 more state for fetching api(default false), when fetch is over set it to false and then in your JSX render relevant component only when isFetching === false.

[isFetching, setIsFetching] = useState(true);
.
.
.
const handleStartGame = async ()=>{
.
.
.
      setIsFetching(false);
   }
.
.
.
return(
    {!isFetching && dealerDeck.map... }
)```