I'm practicing memory game and working on a logic where if two cards are flipped and they are not equal value then flip back to hide the value. Basically,{trackFlip[idx] && cell}
is the part in question. I even console.logged the trackFlip
object from flipBack
function to check to make sure the clicked card value is set to false, and they are, but this conditional rendering still fails. When two unmatched values still display on the screen instead of disappearing. Not sure what's wrong with the logic. https://codesandbox.io/s/frontend-eval-memory-game-ts-8yyfmq?file=/src/App.tsx:0-2438
import "./styles.css";
import React, { useState, useEffect } from "react";
const generateRandomNumbers = (totalNums: number) => {
let halfNums = totalNums / 2;
let count = 0;
let arr = [];
for (let i = 0; i < halfNums; i ) {
arr.push(i);
}
arr = [...arr, ...arr];
let j = arr.length;
while (--j > 0) {
let temp = Math.floor(Math.random() * (j 1));
[arr[temp], arr[j]] = [arr[j], arr[temp]];
}
return arr;
};
interface Hash {
[key: number]: boolean;
}
function createFlipTracker(j: number) {
let hash: Hash = {};
for (let j = 0; j < 36; j ) {
hash[j] = false;
}
return hash;
}
export default function App() {
const [board, setBoard] = useState(generateRandomNumbers(36));
const [trackFlip, setTrackFlip] = useState(createFlipTracker(36));
const [solved, setSolved] = useState<number[]>([]);
const handleClick = (num: number, idx: number) => {
let copiedTrackFlip = { ...trackFlip };
if (copiedTrackFlip[idx]) {
copiedTrackFlip[idx] = false;
setTrackFlip(copiedTrackFlip);
} else {
copiedTrackFlip[idx] = true;
setTrackFlip(copiedTrackFlip);
}
let flippedCell = Object.keys(copiedTrackFlip).filter(
(val) => copiedTrackFlip[Number(val)] === true
);
console.log(flippedCell);
function flipBack(x: number, y: number) {
copiedTrackFlip[x] = false;
copiedTrackFlip[y] = false;
console.log(copiedTrackFlip);
setTrackFlip(copiedTrackFlip);
}
if (flippedCell.length === 2) {
let [x, y] = flippedCell;
if (board[Number(x)] !== board[Number(y)]) {
setTimeout(() => {
flipBack(Number(x), Number(y));
}, 1000);
} else {
setTimeout(() => {
flipBack(Number(x), Number(y));
let copiedSolved = [...solved];
copiedSolved.push(Number(x));
copiedSolved.push(Number(y));
setSolved(copiedSolved);
}, 1000);
}
}
};
const handleWinner = (idx: number) => {
if (solved.includes(idx)) {
return "solvedCell";
}
};
return (
<div className="board-container">
{board.map((cell, idx) => {
return (
<div
className={`cell ${handleWinner(idx)}`}
data-cell={idx}
onClick={() => handleClick(cell, idx)}
>
{trackFlip[idx] && cell}
</div>
);
})}
</div>
);
}
CodePudding user response:
Try this:
function flipBack(x: number, y: number) {
trackFlip[x] = false;
trackFlip[y] = false;
console.log(trackFlip);
setTrackFlip({...trackFlip});
}
Explanation:
It looks like you're setting the copiedTrackFlip
object inside the function, but since it's a copy of the original trackFlip
object and not the actual object, the changes are not being reflected in the component.
Also, you may want to use the spread operator inside the setTrackFlip function to make sure that react knows that this is a new object and should re-render the component.
NB: Not tested but worth a try.