Rock, Paper, Scissors | (NextJS,TailwindCSS,Framer Motion)

Solution retrospective
Hey! I'm Emre and this is my Rock,Paper,Scissors project
There are some problems with my project
- Score doesn't seem to be updating correctly
- Score takes negative values
I think the main problem is due to the use of useEffect
Any suggestions on how I can improve are welcome
GameContext.js
const onSelect = () => {
const userSelect = GameRules[selection].value;
const number = Math.floor(Math.random() * 3);
setHouseSelection(number);
setTimeout(() => {
setShow(true);
if (GameRules[houseSelection].beats.includes(userSelect)) {
setResult("You Lose");
setScore((score) => score - 1);
} else {
if (GameRules[houseSelection].value == userSelect) {
setResult("Tie");
} else {
setResult("You Win");
setScore((score) => score + 1);
}
}
}, 3000);
};
containers\game\index.js
const { onSelect, houseSelection, result, show, playAgain } =
useContext(GameContext);
useEffect(() => {
onSelect();
}, [houseSelection]);
Please log in to post a comment
Log in with GitHubCommunity feedback
- @11kyle
Hey Emre! Great job on your solution! I checked into your question and have some feedback.
- Score takes a negative value.
This can be fixed by wrapping your
setScore((score) => score -1)
inside anif
statement like soif (score > 0) { setScore((score) => score - 1) }
- Score doesn't seem to be updating correctly
You are right on thinking it is the
useEffect
hook that is causing problems here.useEffect
gets called on initial render and again every time anything in the dependency array changes. You also never want to update anything from the dependency array from inside theuseEffect
. This could cause an infinite loop. In your case, theuseEffect
is running a minimum of 2 times and that is part of why you are seeing weird scores. The way your game is setup you can actually leave the dependency array empty like souseEffect(() => { onSelect(); }, []);
In addition, there's a weird thing happening with
useState
inside your GameContext.js.useState
actually takes 'time' to update its value. It's just a part of react. When you setState and then ask your function to do something with it, it is using the previous value. You can replacehouseSelection
withnumber
inside your function like soconst onSelect = () => { const userSelect = GameRules[selection].value; const number = Math.floor(Math.random() * 3); setHouseSelection(number); setTimeout(() => { setShow(true); if (GameRules[number].beats.includes(userSelect)) { setResult("You Lose"); setScore((score) => score - 1); } else { if (GameRules[number].value == userSelect) { setResult("Tie"); } else { setResult("You Win"); setScore((score) => score + 1); } } }, 3000); };
Marked as helpful
Join our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord