So i am trying to implement a bingo game as a small starter react project. If a user gets a word then i want them to be able to click the box and the styling changes so that the box is highlighted green instead for example.
My current implementation of this sort of works and it changes the colour of the boxes but when i try to reset and press ‘new game’ some of the boxes remain highlighted and aren’t reset.
I’ve tried passing in a reset prop to the component to reset the state but this hasnt worked so im left quite confused…
Any ideas on what i could do instead?
Here is my app.js
import { useState, useEffect } from 'react'
import './App.css';
import Cell from './components/Cell';
function App() {
const [words, setWords] = useState([])
const [reset, setReset] = useState(false)
const groupOfWords = [
{ "word": "hello", id: 1},
{ "word": "react", id: 2},
{ "word": "gaming", id: 3},
{ "word": "university", id: 4},
{ "word": "yoooo", id: 5},
{ "word": "hockey", id: 6},
{ "word": "programming", id: 7},
{ "word": "xbox", id: 8},
{ "word": "digging", id: 9},
{ "word": "car", id: 10}
]
const pickRandomWords = () => {
setReset(true)
// Shuffle array
const shuffled = groupOfWords.sort(() => 0.5 - Math.random())
// Get sub-array of first n elements after shuffled
setWords(shuffled.slice(0, 8))
}
return (
<div className="App">
<h1>Bingo</h1>
<button onClick={pickRandomWords}>New Game</button>
<div className='grid'>
{words.map(w => (
<Cell
key={w.id}
word={w.word}
reset={reset}/>
))}
</div>
</div>
);
}
export default App;
this is my cell component
import './Cell.css'
import { useState } from 'react'
export default function Cell({ word, reset }) {
const [matched, setMatched] = useState(reset)
const highlightCell = () => {
setMatched(true)
}
return (
<div className={matched ? 'cell' : 'cellMatched'} onClick={highlightCell}>
<p>{word}</p>
</div>
)
}
>Solution :
The problem is that the same value for reset is being passed to the element. You can pass new values each time you reset, like the current time, and use useEffect to catch that change.
import React from 'react';
import { useState, useEffect } from 'react'
import './style.css';
export function App(props) {
const [words, setWords] = useState([])
const [reset, setReset] = useState(false)
const groupOfWords = [
{ "word": "hello", id: 1},
{ "word": "react", id: 2},
{ "word": "leidos", id: 3},
{ "word": "university", id: 4},
{ "word": "strathclyde", id: 5},
{ "word": "hockey", id: 6},
{ "word": "programming", id: 7},
{ "word": "xbox", id: 8},
{ "word": "hydrocarbon", id: 9},
{ "word": "car", id: 10}
]
const pickRandomWords = () => {
setReset(new Date())
// Shuffle array
const shuffled = groupOfWords.sort(() => 0.5 - Math.random())
// Get sub-array of first n elements after shuffled
setWords(shuffled.slice(0, 8))
}
return (
<div className="App">
<h1>Bingo</h1>
<button onClick={pickRandomWords}>New Game</button>
<div className='grid'>
{words.map(w => (
<Cell
key={w.id}
word={w.word}
reset={reset}/>
))}
</div>
</div>
);
}
function Cell({ word, reset }) {
const [matched, setMatched] = useState(false)
const highlightCell = () => {
setMatched(true)
}
useEffect(()=>{
console.log('reset on', reset)
setMatched(false)
},[reset])
return (
<div className={matched ? 'cellMatched' : 'cell'} onClick={highlightCell}>
<p>{word}</p>
</div>
)
}