reactjs - setTimeout 没有执行(没有错误信息),为什么?
问题描述
我正在做一个记忆游戏。我想要做的是实现以下功能:
当我第一次点击一个正方形时,我希望它显示出来。当我单击第二个正方形时,我也希望它显示。如果两个方块都匹配颜色,则保持显示状态。如果不是,请在重置为黑色之前显示方块 2 秒。
我在第 75 行添加了 setTimout,但我不知道为什么它没有执行。希望能帮助您解决这个问题。
代码:https ://codesandbox.io/s/dreamy-firefly-qdigd?file=/src/App.js
import React, { useState, useEffect } from "react";
import "./styles.css";
function Box({ thing, index, style, updateStatus }) {
return (
<button
type="button"
className="Box"
style={style(index)}
onClick={() => updateStatus(index)}
>
<div>{thing[index].status}</div>
</button>
);
}
function Reset({ newColors, colors, thing }) {
return (
<button type="button" onClick={() => newColors(colors, thing)}>
Reset
</button>
);
}
function App() {
const [status, setStatus] = useState([
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false },
{ status: null, clicked: false }
]);
const [color, setColor] = useState([
"red",
"red",
"yellow",
"yellow",
"blue",
"blue",
"orange",
"orange",
"pink",
"pink",
"purple",
"purple",
"white",
"white",
"green",
"green"
]);
const [holder, setHolder] = useState([]);
function updateStatus(index) {
if (!status[index].clicked) {
const newStatus = [...status];
newStatus[index].clicked = true;
let newHolder = [...holder, { index, color: color[index] }];
if (newHolder.length === 2) {
if (!holderTest(newHolder)) {
setTimeout(function () {
newHolder.map((x) => {
return (newStatus[x.index].clicked = false);
});
}, 2000);
}
newHolder = [];
}
setStatus(newStatus);
setHolder(newHolder);
}
}
console.log(holder.length);
console.log(holder);
console.log(status);
/* function misMatch(newHolder){
return (newHolder.map((x) => {
newStatus[x.index].clicked = false;
}))
} */
function holderTest(holderToTest) {
if (holderToTest[0].color === holderToTest[1].color) {
return true;
}
}
function colorChange(index) {
return { backgroundColor: status[index].clicked ? color[index] : "black" };
}
function resetColor(array, array2) {
const newColors = [...array];
const newArray = [...array2];
for (var i = newColors.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = newColors[i];
newColors[i] = newColors[j];
newColors[j] = temp;
}
newArray.map((x) => {
x.clicked = false;
});
return setColor(newColors), setStatus(newArray);
}
return (
<div>
<Reset newColors={resetColor} colors={color} thing={status} />
<div className="row">
<div className="column">
<Box
thing={status}
index={0}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={1}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={2}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={3}
style={colorChange}
updateStatus={updateStatus}
/>
</div>
<div className="column">
<Box
thing={status}
index={4}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={5}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={6}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={7}
style={colorChange}
updateStatus={updateStatus}
/>
</div>
<div className="column">
<Box
thing={status}
index={8}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={9}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={10}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={11}
style={colorChange}
updateStatus={updateStatus}
/>
</div>
<div className="column">
<Box
thing={status}
index={12}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={13}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={14}
style={colorChange}
updateStatus={updateStatus}
/>
<Box
thing={status}
index={15}
style={colorChange}
updateStatus={updateStatus}
/>
</div>
</div>
</div>
);
}
export default App;
解决方案
它比你想象的要容易...
const initialColors = [
{ color: "red", active: false },
{ color: "red", active: false },
{ color: "yellow", active: false },
{ color: "yellow", active: false },
{ color: "blue", active: false },
{ color: "blue", active: false },
{ color: "orange", active: false },
{ color: "orange", active: false },
{ color: "pink", active: false },
{ color: "pink", active: false },
{ color: "purple", active: false },
{ color: "purple", active: false },
{ color: "white", active: false },
{ color: "white", active: false },
{ color: "green", active: false },
{ color: "green", active: false },
];
let lastColor = null;
let lastTimer = null;
function Game() {
const [colors, setColors] = React.useState(initialColors.sort(()=>Math.random()-0.5));
const changeColor = (index) =>
setColors((prev) =>
prev.map((x, i) => (i === index ? { ...x, active: !x.active } : x))
);
const clickHandler = (index) => {
if (colors[index].active) return;
else changeColor(index);
if (lastColor === colors[index].color) {
clearTimeout(lastTimer);
} else {
lastTimer = setTimeout(() => {
changeColor(index);
}, 1000);
}
lastColor = colors[index].color;
};
const resetGame = () => {
lastColor = null;
clearTimeout(lastTimer);
setColors(initialColors.sort(()=>Math.random()-0.5));
};
return (
<div>
<button onClick={resetGame}>Rest</button>
<div
style={{
display: "flex",
flexFlow: "wrap",
maxWidth: 200,
maxHeight: 200,
justifyContent: "space-between",
margin: "auto",
}}
>
{colors.map(({color,active}, i) => (
<button
key={i}
style={{
backgroundColor: active ? color : "black",
height: 50,
width: 50,
}}
onClick={() => clickHandler(i)}
/>
))}
</div>
</div>
);
}
ReactDOM.render(
<Game />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
推荐阅读
- python - 如何使用另一个文件进行打印(“{}”)?
- dictionary - 在 Julia 中按顺序打印整数字典
- powershell - 使用 Move-Item 时文件已存在时,Powershell 无法创建文件
- vue.js - 加载资源失败:net::ERR_HTTP2_PROTOCOL_ERROR -Vue.js 部署在 IIS10
- java - Java类图中带有接口参数的构造函数
- javascript - 面临断开链接检查器的问题
- json - 需要一个“int”类型的值,但在 Flutter 中得到一个“String”类型的值
- python - 如何为每个子图设置不同的 x 和 y 轴?
- file-copying - 如何将 Google Drive 文件从一个帐户移动到另一个帐户,以保留与其他人共享的访问权限
- javascript - 反应布尔属性不起作用,视频不自动播放