这是实时网站:https://luxury-stroopwafel-b36b51.netlify.app/ 这是 Github 存储库:https://github.com/FullStackPete/CatMemoryGame
我的动画有问题。当我单击猫的图像时 - 包含猫数据的数组正在被洗牌,然后被重新渲染。所以它是这样的:你点击一只猫 -> 卡片翻转 -> allData 数组正在被洗牌 -> 卡片(应该)以动画方式展开。 但您可能会注意到,只有翻转后具有相同 ID 的卡片才会获得动画效果。所有洗过的牌都会立即“呈现”为
cardIsActive(false)
- 这是我负责翻转牌的状态。当我注释掉 shuffleData(allData);
行时,所有动画都已正确完成,但卡片没有被洗牌,因此游戏没有任何意义。请帮我解决这个问题。
负责翻转的库(虽然我不认为它会引起问题):https://www.npmjs.com/package/react-card-flip
应用程序.jsx
const shuffleData = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
};
const handleHowToPlayClick = () => {
setShowInstructions(!showInstructions);
};
const handleCardClick = (data) => {
setCardIsActive(false);
setTimeout(()=>{
setCardIsActive(true);
},500);
if (!pickedCards.includes(data.id)) {
setPickedCards((prev) => [...prev, data.id]);
setCardsLeft((prev) => prev.filter((item) => item !== data.id));
shuffleData(allData);
if (pickedCards.length >= highestWin) {
setHighestWin(pickedCards.length);
}
} else {
//Lose Logic
setLose((prev) => prev + 1);
setCurrentRound(3);
setPickedCards([]);
}
};
useEffect(() => {
if (pickedCards.length > highestWin) {
setHighestWin(pickedCards.length);
}
if (cardsLeft.length === 0) {
setWin((prev) => prev + 1);
setCurrentRound((prev) => prev + 2);
}
}, [cardsLeft]);
return (
//code responsible for rendering - not important
)
Cards.jsx
export function Cards({ handleCardClick, setAllCards, setCardsLeft, lose, allData, setAllData, cardIsActive, win, currentRound,
}) {
const chunkSize = 3;
const CatApi = `https://api.thecatapi.com/v1/images/search?limit=${currentRound}&api_key=${
import.meta.env.VITE_CatApiKey
}`;
useEffect(() => {
const fetchData = async () => {
try {
const res = await axios.get(CatApi);
setAllData(res.data);
const cardIds = res.data.map((data) => data.id);
setAllCards(cardIds);
setCardsLeft(cardIds);
} catch (err) {
console.log("Error fetching data: ", err);
}
};
fetchData();
}, [lose, win]);
const chunkedData = Array.from(
{ length: Math.ceil(allData.length / chunkSize) },
(_, index) => allData.slice(index * chunkSize, (index + 1) * chunkSize)
);
return (
<div className="flex flex-col items-center justify-center mt-8">
{chunkedData.map((chunk, index) => (
<div className="flex flex-row" key={index}>
{chunk.map((data) => (
<>
<Tilt
tiltMaxAngleX="15"
tiltMaxAngleY="15"
key={data.id}
className="!p-0 m-4 background-color !rounded-xl aspect-[3/4] max-h-60 min-h-60 lg:max-h-80 lg:min-h-80"
>
<ReactCardFlip
flipDirection="horizontal"
isFlipped={cardIsActive}
>
<img
onClick={() => handleCardClick()}
className="aspect-[3/4] max-h-60 min-h-60 lg:max-h-80 lg:min-h-80 rounded-xl card-shadow hover:cursor-pointer"
src={CardBackground}
/>
<img
onClick={() => handleCardClick(data)}
className="object-cover aspect-[3/4] max-h-60 min-h-60 lg:max-h-80 lg:min-h-80 rounded-md card-shadow hover:cursor-pointer"
key={data.id}
src={data.url}
//
/>
</ReactCardFlip>
</Tilt>
</>
))}
</div>
))}
</div>
);
}
这是一个渲染问题。事实证明,在我对数据进行洗牌后,没有后续重新渲染。所以我为此添加了一个特殊状态
const [render, setRender] = useState(-1);
之后在我的handleCardClick中添加了一些超时:
const handleCardClick = (data) => {
setCardIsActive(false);
if (!pickedCards.includes(data.id)) {
setPickedCards((prev) => [...prev, data.id]);
setCardsLeft((prev) => prev.filter((item) => item !== data.id));
setTimeout(()=>{shuffleData(allData);},100)
setTimeout(() => {
setRender((prev) => prev + 1);
}, 650);
setTimeout(() => {
setCardIsActive(true);
}, 1000);
if (pickedCards.length >= highestWin) {
setHighestWin(pickedCards.length);
}
} else {
//Lose Logic
setCardIsActive(false);
setLose((prev) => prev + 1);
setCurrentRound(3);
setPickedCards([]);
}
};