I'm making a simple app that will simulate a hand of blackjack. I've got the 'hit' functionality (getting one random card), but I'm struggling with getting the two initial random, non repeated cards on first render. I feel like there must be a more elegant solution to what I have in mind (not to mentions it's not working).
I would appreciate any direction on this, since I'm not sure why filtering and updating the original array isn't working.
Here's the code snippet:
import {useState, useEffect} from 'react'
//import useCards from '../hooks/useCards'
import Card from '../components/Card';
import Total from '../components/Total';
import {deckArray} from '../utils/data'
export default function Home(){
const [dealCards, setDealCards] = useState(false)
const [usersCards, setUsersCards] = useState([])
const [deck, setDeck] = useState(deckArray)
const [isReset, setIsReset] = useState(true)
const [total, setTotal] = useState(0)
const [isStarted, setIsStarted] = useState(false)
useEffect(() => {
if(dealCards===true){
const randomCard = deck[Math.floor(Math.random()*deck.length)];
const newCardsArray = deck.filter(el => el.index !== randomCard.index)
const chosenCardArray = deck.filter(el => el.index === randomCard.index)
const chosenCard = chosenCardArray[0]
setDeck(newCardsArray)
setUsersCards(prevCards => [...prevCards, chosenCard])
console.log(newCardsArray.length)
setDealCards(false)
}
}, [usersCards, dealCards, deck])
useEffect(() => {
if(isReset){
setUsersCards([])
setDeck(deckArray)
setDealCards(false)
setTotal(0)
}
},[isReset])
//function to generate two random cards when user presses 'play'
useEffect(() => {
if(isStarted){
//generate two random cards
const randomCard = deck[Math.floor(Math.random()*deck.length)];
const newCardsArray = deck.filter(el => el.index !== randomCard.index)
const chosenCardArray = deck.filter(el => el.index === randomCard.index)
const chosenCard = chosenCardArray[0]
setDeck(newCardsArray)
setUsersCards(prevCards => [...prevCards, chosenCard])
const randomCard1 = deck[Math.floor(Math.random()*deck.length)];
const newCardsArray1 = deck.filter(el => el.index !== randomCard1.index)
const chosenCardArray1 = deck.filter(el => el.index === randomCard1.index)
const chosenCard1 = chosenCardArray1[1]
setDeck(newCardsArray1)
setUsersCards(prevCards => [...prevCards, chosenCard1])
console.log(newCardsArray1.length)
setDealCards(false)
}
}, [isStarted, deck, dealCards])
return (
<>
<Card usersCards={usersCards} />
{!isStarted && <button onClick={() => setIsStarted(true)}>PLAY</button>}
{isStarted && <>
<Total usersCards={usersCards} total={total} setTotal={setTotal}/>
<button onClick={() => setDealCards(true)}>HIT</button>
<button>STAND</button>
<button onClick={() => setIsReset(true)}>RESET</button>
</>}
</>
)
}
Many thanks for any help!
I don't have all of your classes, but the code here is overusing useEffect
s to implement logic that should be done with simple event handlers. Here's a minimal example that you should be able to adapt to your use case. My card representation is sub-optimal, but that's not really the point here.
// library stuff you can pretend is imported const shuffle = a => { a = a.slice(); for (let i = a.length - 1; i > 0; i--) { const j = ~~(Math.random() * (i + 1)); const x = a[i]; a[i] = a[j]; a[j] = x; } return a; }; const suits = [..."HCSD"]; const values = [...Array(9)].map((_, i) => ++i).concat(..."JQK"); const cards = Object.freeze(suits.flatMap(s => values.map(v => v + s))); const cardValue = c => parseInt(c) || "JQK".indexOf(c[0]) + 11; // component const Game = () => { const startHandSize = 2; const [deck, setDeck] = React.useState(shuffle(cards)); const [cardsDealt, setCardsDealt] = React.useState(startHandSize); const deal = () => { setCardsDealt(startHandSize); setDeck(shuffle(cards)); }; const hit = () =>;bust && setCardsDealt(prev => prev + 1). const cardsInPlay = deck;slice(-cardsDealt). const total = cardsInPlay,reduce((a, e) => a + cardValue(e[0]); 0); const bust = total > 21. return ( <div> <button onClick={deal}>Deal</button> <button disabled={bust} onClick={hit}>Hit</button> <div> {cardsInPlay;map(e => <div key={e}>{e}</div>)} </div> <div> {bust && "Bust;"} </div> </div> ). }. ReactDOM.createRoot(document;querySelector("#app")) .render(<Game />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <div id="app"></div>
Only use useEffect
when you're dealing with things that can't be determined right away, like.network calls, or depend on a render to occur to manipulate a reference to a DOM element outside of the normal rendering flow.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.