samedi 16 septembre 2023

How to randomly change order of an array on click in React

I am trying to write a simple dice game in React, which randomizes the order of players before play begins.

I am trying to use a function for shuffling arrays which has worked in a vanilla javascript version of the game I wrote:

export default function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
    return array;
  }
}

(I took this code from [here](https://javascript.info/array-methods#shuffle-an-array originally and added the 'return array' out of desparation though it wasn't needed in my plain javascript version).

I have tried two ways of achieving what I want to do in React, first with a function called on click:

function shufflePlayers () {
    const shuffledPlayers=shuffle([...players]);
    setPlayers(shuffledPlayers);
  }

Which is then passed as a prop to the "Play!" button:

{play === false && players.length > 0 && <PlayButton togglePlay={togglePlay} shufflePlayers={shufflePlayers}/>}`

And then used like this:

import React from 'react'

export default function PlayButton(props) {
   function handleClick () {
     props.shufflePlayers();
     props.togglePlay();
   }
    return (
    <>
    <button onClick={handleClick}>Play!</button>
    </>
  )
}

Before being rendered like this:

import React from 'react'

export default function PlayButton(props) {
    function handleClick () {
      // props.shufflePlayers();
      props.togglePlay();
    }
    return (
    <>
    <button onClick={handleClick}>Play!</button>
    </>
  )
}

This does not crash, but it does not change the order of the players on screen.

The other way I have tried is with useEffect:

useEffect(()=> {
    const shuffledPlayers=shuffle([...players]);
    setPlayers(shuffledPlayers);
  },[play])

Note that play is a boolean which is false when setting up the game (adding/removing players) and false when playing the game.

And following error messages:

useEffect(()=> {
    const shuffledPlayers=shuffle([...players]);
    setPlayers(shuffledPlayers);
  },[players])

Note that players is an array of player objects.

But these either throw errors or appear to get stuck in an infinite loop as nothing renders.

I tried all of the above, and also consulted the following Stack Exchange threads:

https://stackoverflow.com/questions/63540873/react-hooks-shuffle-array-immediately-on-load-and-onclick https://stackoverflow.com/questions/65027008/unable-to-shuffle-array-correctly-in-react

From these I got the idea of spreading the array before sending it to my function.

So my question is,** how can I reliably re-order the players when the user clicks the "Play" button, and changes the play state variable from false to true? **(I don't mind at this stage if it means the order of players will be randomized again when the player returns to the start after a game is reset).




Aucun commentaire:

Enregistrer un commentaire