使用useContext的子组件中的未定义状态

时间:2019-11-18 22:48:18

标签: reactjs react-hooks

我正在用React构建一个snake game。蛇(状态切片snakeDots的坐标每秒更新一次,新状态应反映在Snake组件中,该组件将蛇显示到屏幕上。我正在使用useReduce,所以我可以同步更新State,并且正在使用useContext将状态扩展到子组件。第一次渲染时,状态(snakeDots)未定义时出现错误。不知道为什么,因为状态具有初始值。谁能阐明一些想法?谢谢

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();
        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.jsx中:

import React, { useContext } from "react";

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

export default function Snake () {
  debugger
  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();

编辑:

错误消息是: TypeError: Cannot read property 'snakeDots' of undefined中的Snake.js,该组件甚至不呈现第5行。

1 个答案:

答案 0 :(得分:1)

我看到了你的问题。您正在关闭第一个提供程序,而不是包装蛇组件,而是创建两个没有子级的提供程序。将App.js中的返回值更改为:

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

您当前拥有的内容(固定缩进以查看错误)

  return (
    <div className="game-area">
      {/* First provider */}
      <snakeContext.Provider value={{ snakeDots, food }} />

      <Snake />

      <Food dot={food} />

      {/* Second provider */}
      <snakeContext.Provider />
    </div>
  );

Snake不是任何提供程序的子级,而是同级。