From 4142987c85461e3a36909bb44d8122196c8fddf3 Mon Sep 17 00:00:00 2001 From: devanshu Date: Tue, 7 Oct 2025 13:56:22 +0530 Subject: [PATCH 1/4] Fix ReferenceError by removing obsolete hint refs and updating cleanup logic --- src/App.js | 153 +++++++++++++---------------------------------------- 1 file changed, 38 insertions(+), 115 deletions(-) diff --git a/src/App.js b/src/App.js index 78ccb40..644158d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,3 @@ -// src/App.js import { useEffect, useState, useMemo, useCallback, useRef } from "react"; import { nanoid } from "nanoid"; import "./App.css"; @@ -12,6 +11,7 @@ import CustomCursor from "./components/CustomCursor/CustomCursor"; import { cardImages } from "./data/cardImages"; import { numbers } from "./constants/numbers"; import { secureShuffleArray, pickRandomImages } from "./utils/logic"; +import { useHint } from "./utils/useHint"; function App() { const [cards, setCards] = useState([]); @@ -24,16 +24,8 @@ function App() { const [celebrationStatus, setCelebrationStatus] = useState(false); const [elapsedTime, setElapsedTime] = useState(undefined); const intervalRef = useRef(null); - const hintTimeoutRef = useRef(null); - const hintIntervalRef = useRef(null); - const hintLockedRef = useRef(false); - const [hintCount, setHintCount] = useState(3); - const [hintCooldown, setHintCooldown] = useState(0); - const [hintActive, setHintActive] = useState(false); const [animateCollapse, setAnimateCollapse] = useState(false); const [gameOverMessage, setGameOverMessage] = useState(false); - const REVEAL_DURATION = 2000; - const HINT_COOLDOWN = 5000; const soundEffect = useMemo(() => { const audio = new Audio(); @@ -70,6 +62,21 @@ function App() { } }, []); + const { + hintCount, + hintCooldown, + hintActive, + hintCards, + resetHints, + } = useHint({ + cards, + handleTime, + setChoiceOne, + setChoiceTwo, + setTurns, + setDisabled, + }); + const clearTimer = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); @@ -77,81 +84,6 @@ function App() { } }, []); - const hintCards = useCallback(() => { - if (hintActive || hintLockedRef.current) return; - - if (!cards || cards.length === 0) return; - if (hintCount === 0) return; - - setHintCount((c) => c - 1); - hintLockedRef.current = true; - if (elapsedTime === undefined) handleTime(true); - const seconds = Math.floor(HINT_COOLDOWN / 1000); - setHintCooldown(seconds); - if (hintIntervalRef.current) clearInterval(hintIntervalRef.current); - hintIntervalRef.current = setInterval(() => { - setHintCooldown((s) => { - if (s <= 1) { - clearInterval(hintIntervalRef.current); - hintIntervalRef.current = null; - hintLockedRef.current = false; - return 0; - } - return s - 1; - }); - }, 1000); - - const available = cards.map((c, i) => ({ c, i })).filter(({ c }) => !c.matched); - if (available.length === 0) { - if (hintIntervalRef.current) { - clearInterval(hintIntervalRef.current); - hintIntervalRef.current = null; - } - setHintCooldown(0); - hintLockedRef.current = false; - return; - } - - if (available.length === 1) { - setHintActive(true); - setDisabled(true); - setChoiceOne(available[0].c); - setChoiceTwo(null); - - if (hintTimeoutRef.current) clearTimeout(hintTimeoutRef.current); - hintTimeoutRef.current = setTimeout(() => { - setChoiceOne(null); - setChoiceTwo(null); - setHintActive(false); - setDisabled(false); - }, REVEAL_DURATION); - - return; - } - - const idxA = crypto.getRandomValues(new Uint32Array(1))[0] % available.length; - - let idxB = crypto.getRandomValues(new Uint32Array(1))[0] % (available.length - 1); - if (idxB >= idxA) idxB += 1; - - const cardA = available[idxA].c; - const cardB = available[idxB].c; - - setHintActive(true); - setDisabled(true); - setChoiceOne(cardA); - setChoiceTwo(cardB); - setTurns(turns + 1); - - if (hintTimeoutRef.current) clearTimeout(hintTimeoutRef.current); - hintTimeoutRef.current = setTimeout(() => { - setChoiceOne(null); - setChoiceTwo(null); - setHintActive(false); - setDisabled(false); - }, REVEAL_DURATION); - }, [cards, hintCount, hintActive]); - const shuffledCards = useCallback(() => { const selected = pickRandomImages(cardImages, 6); const dup = [...selected, ...selected] @@ -171,18 +103,17 @@ function App() { setMatched(0); setCelebrationStatus(false); setElapsedTime(undefined); - clearTimer(); + setAnimateCollapse(true); setTimeout(() => setAnimateCollapse(false), 1200); setGameOverMessage(false); - }, [clearTimer]); + }, []); const handleNewGame = useCallback(() => { - setHintCount(3) - setHintCooldown(0); + resetHints(); playSound("audio/start.mp3"); shuffledCards(); - }, [playSound, shuffledCards]); + }, [playSound, shuffledCards, resetHints]); const handleChoice = useCallback( (card) => { @@ -215,7 +146,7 @@ function App() { } else if (choiceOne) { playSound("/audio/swap.wav"); } - }, [choiceOne, choiceTwo, resetTurn, playSound]); + }, [choiceOne, choiceTwo, resetTurn, playSound, hintActive]); useEffect(() => { if (matched === cards.length && turns) { @@ -246,18 +177,9 @@ function App() { setHighScore(hs); return () => { clearTimer(); - if (hintTimeoutRef.current) { - clearTimeout(hintTimeoutRef.current); - hintTimeoutRef.current = null; - } - if (hintIntervalRef.current) { - clearInterval(hintIntervalRef.current); - hintIntervalRef.current = null; - } - hintLockedRef.current = false; - setHintCooldown(0); + resetHints(); }; - }, [shuffledCards, clearTimer]); + }, [shuffledCards, clearTimer, resetHints]); return (
@@ -273,24 +195,25 @@ function App() { A&A Match
- -
- -

{hintCount === 1 ? "Hint Remaining: " : "Hints Remaining: "}{hintCount}

-
+ +
+ +

+ {hintCount === 1 ? "Hint Remaining: " : "Hints Remaining: "} + {hintCount} +

+
-
+
{cards.map((card) => ( Date: Tue, 7 Oct 2025 20:53:47 +0530 Subject: [PATCH 2/4] Refactor: cleaned up hint logic, fixed reference errors, and updated structure for stability --- package-lock.json | 55 -------------- public/index.html | 3 +- src/components/singlecard/SingleCard.js | 17 ++++- src/index.js | 9 +-- src/utils/useHint.js | 96 +++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 63 deletions(-) create mode 100644 src/utils/useHint.js diff --git a/package-lock.json b/package-lock.json index e959344..6ae3b5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4186,26 +4186,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", - "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -4373,13 +4353,6 @@ "node": ">=10.13.0" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "license": "MIT", - "peer": true - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -19438,20 +19411,6 @@ } } }, - "node_modules/tailwindcss/node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", @@ -19951,20 +19910,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/public/index.html b/public/index.html index 24639aa..9ea38f4 100644 --- a/public/index.html +++ b/public/index.html @@ -2,8 +2,7 @@ - - + diff --git a/src/components/singlecard/SingleCard.js b/src/components/singlecard/SingleCard.js index 25269bd..cd025a4 100644 --- a/src/components/singlecard/SingleCard.js +++ b/src/components/singlecard/SingleCard.js @@ -13,8 +13,21 @@ export default function SingleCard({ card, handleChoice, flipped, disabled }) {
- card front blur background - card front + card front blur background +card front +
- +
{cards.map((card) => (