在子组件中未更新带有挂钩的同步状态片

时间:2019-11-19 22:21:05

标签: reactjs react-hooks

我正在用React Hooks构建snake gamesnakeDots状态包含蛇在板上的位置。这样,新状态取决于先前的状态(如果向右移动,它会在先前的X坐标上加上2,依此类推)。由于状态是设计上与React Hooks异步的,因此我认为使其同步的方法是使用useContext,这就是我所做的。虽然在reducer内放置调试器会告诉我状态正确更新(setInterval并且reducer有效),但snakeDots组件可用的Snake.js并未更新。由于一切似乎都已正确连接,因此不确定发生了什么。结果,蛇是静态的,因为坐标不变。谁能阐明一些想法?非常感谢!下面的代码:

App.js中的代码:

import React, { useState, useEffect, useReducer } from "react";
import Snake from "./Snake";
import Food from "./Food";

import { snakeContext } from "./contexts/snakeContext";

const getRandomCoordinates = () => {
  let min = 1;
  let max = 98;
  let x = Math.floor((Math.random() * (max - min + 1) + min) / 2) * 2;
  let y = Math.floor((Math.random() * (max - min + 1) + min) / 2) * 2;
  return [x, y];
};

function App() {
  const [snakeDots, dispatch] = useReducer(reducer, [
    [0, 0],
    [2, 0]
  ]);

  const [food, setFood] = useState(getRandomCoordinates());

  const [direction, setDirection] = useState("RIGHT");

  const [speed, setSpeed] = useState(200);

  useEffect(() => {
    setInterval(() => dispatch({ type: direction }), speed);
    document.onkeydown = onKeyDown;
  }, []);

  function onKeyDown(e) {
    e = e || window.event;
    switch (e.keyCode) {
      case 38:
        setDirection("UP");
        break;
      case 40:
        setDirection("DOWN");
        break;
      case 37:
        setDirection("LEFT");
        break;
      case 39:
        setDirection("RIGHT");
        break;
      default:
        console.log("wrong key");
    }
  }

  function reducer(snakeDots, action) {
    switch (action.type) {
      case "RIGHT":
        let head = snakeDots[snakeDots.length - 1];
        head = [head[0] + 2, head[1]];
        snakeDots.push(head);
        snakeDots.shift();
        debugger
        return snakeDots;
      default:
        throw new Error();
    }
  }

  return (
    <div className="game-area">
      <snakeContext.Provider value={{ snakeDots, food }}>
        <Snake />
        <Food dot={food} />
      </snakeContext.Provider>
    </div>
  );
}

export default App;

Snake.js中的代码:

import React, { useContext } from "react";

import { snakeContext } from "./contexts/snakeContext";

export default function Snake() {
  const { snakeDots } = useContext(snakeContext);
  debugger
  return (
    <div>
      {snakeDots.map((dot, i) => {
        const style = {
          left: `${dot[0]}%`,
          top: `${dot[1]}%`
        };
        return <div className="snake-dot" key={i} style={style}></div>;
      })}
    </div>
  );
}

snakeContext.js中的代码:

import { createContext } from "react";
export const snakeContext = createContext();

0 个答案:

没有答案