首页 > 解决方案 > 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;

标签: reactjsreact-hooks

解决方案


它比你想象的要容易...

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>


推荐阅读