Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React – change styling of component onClick and reset

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…

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>
    )
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading