Tell us what’s happening:
Hello! I’m working on the [Insert Project Name Here] project and I’m running into an issue where clicking the “Check Your Code” button causes the tests to run infinitely. It doesn’t crash or log an “infinite loop” error, it just hangs.
I suspect the issue is coming from my useEffect that handles the idle game state (updating hunger and happiness).
Here is the code:
useEffect(() => {
if (!gameStarted) return;
const timer = setInterval(() => {
setHunger((prev) => Math.min(100
Your code so far
<!-- file: index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Digital Pet Game</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Tektur:wght@400..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
<script
data-plugins="transform-modules-umd"
type="text/babel"
src="index.tsx"
></script>
</head>
<body>
<div id="root"></div>
<script
data-plugins="transform-modules-umd"
type="text/babel"
data-presets="react"
data-type="module"
>
import { PetGame } from './index.tsx';
ReactDOM.createRoot(document.getElementById('root')).render(<PetGame />);
</script>
</body>
</html>
/* file: index.tsx */
const { useState, useEffect, useRef } = React;
export enum Action {
EAT = "EAT",
PLAY = "PLAY",
SLEEP = "SLEEP"
}
export enum PetMood {
HAPPY,
EXCITED,
CONTENT,
SAD,
TIRED,
SICK,
HUNGRY
}
const moodEmojis: Record<PetMood, string> = {
[PetMood.HAPPY]: "😊",
[PetMood.EXCITED]: "🤩",
[PetMood.CONTENT]: "🙂",
[PetMood.SAD]: "😢",
[PetMood.TIRED]: "😴",
[PetMood.SICK]: "🤒",
[PetMood.HUNGRY]: "🍔"
};
export function PetGame() {
const [petName, setPetName] = useState("");
const [gameStarted, setGameStarted] = useState(false);
const nameInputRef = useRef<HTMLInputElement>(null);
const [hunger, setHunger] = useState(0);
const [happiness, setHappiness] = useState(100);
const [energy, setEnergy] = useState(100);
useEffect(() => {
if (!gameStarted) return;
const timer = setInterval(() => {
setHunger((prev) => Math.min(100, prev + 10));
setHappiness((prev) => Math.max(0, prev - 10));
}, 100);
return () => clearInterval(timer);
}, [gameStarted]);
const getMood = (): PetMood => {
if (hunger > 70) {
return PetMood.HUNGRY;
}
if (energy < 30) {
return PetMood.TIRED;
}
if (happiness < 30) {
return PetMood.SAD;
}
if (happiness > 80 && energy > 70) {
return PetMood.EXCITED;
}
if (happiness > 60) {
return PetMood.HAPPY;
}
return PetMood.CONTENT;
};
const handleAction = (action: Action): void => {
switch(action) {
case Action.EAT:
setHunger((prev) =>
prev > 0 ? prev - 10 : prev
);
setEnergy((prev) =>
prev < 100 ? prev + 10 : prev
);
break;
case Action.PLAY:
setEnergy((prev) =>
prev > 0 ? prev - 10 : prev
);
setHappiness((prev) =>
prev < 100 ? prev + 10 : prev
);
break;
case Action.SLEEP:
setHunger((prev) =>
prev < 100 ? prev + 10 : prev
);
setEnergy((prev) =>
prev < 100 ? prev + 10 : prev
);
break;
}
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
if (!nameInputRef.current) {
return;
}
const name = nameInputRef.current.value.trim();
if (name) {
setPetName(name);
setGameStarted(true);
}
};
return (
<div>
{!gameStarted ? (
<form onSubmit={handleSubmit}>
<label htmlFor="pet-name">
Name your pet
</label>
<input
id="pet-name"
type="text"
ref={nameInputRef}
/>
<button type="submit">
Start Game
</button>
</form>
) : (
<div>
<h2 className="pet-name">
{petName}
</h2>
<div>
{moodEmojis[getMood()]}
{" "}
{PetMood[getMood()]}
</div>
<div className="stat">
<span>
Hunger
</span>
<span className="stat-value">
{hunger}
</span>
</div>
<div className="stat">
<span>
Happiness
</span>
<span className="stat-value">
{happiness}
</span>
</div>
<div className="stat">
<span>
Energy
</span>
<span className="stat-value">
{energy}
</span>
</div>
<button
id="eat-action"
onClick={() =>
handleAction(Action.EAT)
}
>
EAT
</button>
<button
id="play-action"
onClick={() =>
handleAction(Action.PLAY)
}
>
PLAY
</button>
<button
id="sleep-action"
onClick={() =>
handleAction(Action.SLEEP)
}
>
SLEEP
</button>
</div>
)}
</div>
);
}
/* file: styles.css */
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36 OPR/133.0.0.0
Challenge Information:
Build a Digital Pet Game - Build a Digital Pet Game