我正在 React 上用纸牌做一个记忆游戏。该游戏是关于不重复地点击卡片来获得分数的,如果你点击卡片两次,你几乎会输掉。现在,这是 Odin 项目 的一个教育项目,其目标是练习 React 状态。
问题描述
App
像游戏管理员一样存储点击了哪些卡片。 Set
洗牌并模拟将它们放在桌子上的过程。 Card
只负责触发应用程序checkClicked(name)
功能更新哪些卡片已被点击的卡片。我一开始的想法是将点击的卡片存储在一个状态中,以跟踪用户的交互。
我可以将
checkClicked(name)
函数传递给 Card
所以 Set
可以将它的任何卡片名称作为函数参数发送。为什么我不直接从checkClicked(name)
触发Set
。好问题,问题是 Card name
prop 不能直接作为参数传递,希望这是有道理的。
让我们进入正题,好吗?我知道状态是异步工作的,所以问题是如果
clicked
是一个状态,它不会被更新,而将 clicked
声明为变量很容易解决整个问题。这是为什么?理想情况下,我应该使用状态来处理随时间变化的数据,但我也阅读了一些与 Stackoverflow 相关的帖子,变量会代替它。这让我问,那我应该什么时候去州?
App.js
import './App.css';
import Set from './components/set';
import Score from './components/score';
import {useState} from 'react';
function App() {
let clicked = []
function checkClicked(name){
alert(`Calling ${name} from app.js`)
if(clicked[4]){
//Reset clicked - current score - best score
}else{
if(clicked.find(click => click === name)){
//Reset current score
alert('Found')
}
else{
//Update clicked - Check best - increase current
clicked.push(name)
}
}
alert(clicked);
}
return (
<>
<Score/>
<Set action={checkClicked}/>
</>
);
}
export default App;
Set.js
import {useState} from "react";
import uniqid from "uniqid";
import Card from "./card";
export default function Set(props){
const[cards,setCards] = useState([<Card key={uniqid()} onClick={handleAction} name="John" pic="1"/>,
<Card key={uniqid()} onClick={handleAction} name="Al" pic="2"/>,
<Card key={uniqid()} onClick={handleAction} name="Paul" pic="3"/>,
<Card key={uniqid()} onClick={handleAction} name="James" pic="4"/>,
<Card key={uniqid()} onClick={handleAction} name="Lou" pic="5"/>,]);
function handleAction(name){
props.action(name);
shuffle();
}
function shuffle(){
const shuffled = Array(5);
let random;
cards.forEach(card=>{
while(true){
random = Math.floor(Math.random()*5);
if(!shuffled[random]){
shuffled[random] = card;
break;
}
}
});
setCards(shuffled);
}
return(
<>
<button onClick={()=>shuffle()}>Shuffle</button>
{cards}
</>
);
}
Card.js
export default function Card(props){
function handleClick(){
props.onClick(props.name);
}
return(
<div onClick={handleClick}>
<p>{props.name}</p>
<p>{props.pic}</p>
</div>
);
}
我相信项目结构是正确的,但我也想请你们进行审查,因为也许有一些我现在看不到的东西会产生负面影响,并且也与我正在描述的问题有关。
干杯!
只要状态更改更改可能触发重新渲染,您就想使用状态。在您的示例中,您只需使用 clicked 进行一些计算,不需要重新渲染。相反,如果您在 JSX 中显示点击列表,则需要将其置于一个状态。
附注我注意到您在 Set.js 中以您的状态存储组件。这是不受欢迎的(参见 Is it a good idea to store components in state?)