I’m building a fast-paced game where the user collects animals through matching. The game works as follows: The user is presented with 2 pictures of 2 animals, and they must cycle through the pictures by pressing 2 buttons, one that changes the top picture and one that changes the bottom. When the top picture and bottom picture match, that animal is collected and put in the user’s bestiary.
You can try it here: https://animal-snipet.web.app/
I’m trying to filter data from animalData
that corresponds with the user’s caught animals so that these animals don’t show up in the next game. Ideally, the code snippet below would push a filtered array that consists of animals the user hasn’t caught yet, and then, in the next game, animal data
would be assigned to this new array. All my attempts at coding this have resulted in the top and bottom indexes rapidly switching through all the pictures and breaking my app.
Here are the relevant code snippets
//The code that executes whenever a button is clicked. There’s an identical function named voteTop that mirros what voteBottom does.
import React, { useState, useEffect } from "react";
function App() {
const [animalData, setAnimalData] = useState(["Dog", "Cat", "Bird"]); // Sample data
const [matchedAnimals, setMatchedAnimals] = useState([]);
// Simulating vote function
const vote = () => {
const randomIndex = Math.floor(Math.random() * animalData.length);
const matchedAnimal = animalData[randomIndex];
setMatchedAnimals(prevMatchedAnimals => [...prevMatchedAnimals, matchedAnimal]);
setAnimalData(prevAnimalData => prevAnimalData.filter((_, index) => index !== randomIndex));
};
return (
<div>
<h2>Animal Data</h2>
<ul>
{animalData.map((animal, index) => (
<li key={index}>{animal}</li>
))}
</ul>
<button onClick={vote}>Vote</button>
<h2>Matched Animals</h2>
<ul>
{matchedAnimals.map((animal, index) => (
<li key={index}>{animal}</li>
))}
</ul>
</div>
);
}
export default App;
Firebase Setup:
I’m using Firebase to store the animal data and matched animals. Here’s how the data is structured:
animalData
array: stored in the Firebase Realtime Database under the "unclaimed" node.matchedAnimals
array: stored in the Firebase Realtime Database under the "matchedAnimals" node.
I’m using the Firebase SDK to read and write data to these nodes.
Expected behavior:
After a game ends, the previously matched animals should be filtered out from the animalData
array, so that the next game starts with a fresh set of animals.
2
Answers
I have no idea what your objects look like but, it seems like you could filter possible matched cards with ids and still keep it O(1) the 1 being the total list of animals
Instead of trying to do all the work in a button’s
onClick
handler that is effectively duplicated across two vote button’s callbacks, I suggest adding some React state that holds the randomly generated indices and the button callbacks just update these state. Move the logic to test for matches between button/voting indices into auseEffect
hook.Example:
Full Demo: