为什么每两次按键只触发一次渲染?

问题描述 投票:0回答:1

问题:

目标:每次我按下“W+C+N”键时,屏幕上会随机出现一个图像。

实际结果:图像仅每两次按键出现一次。例如,如果我在“W+C+N”上按 4 次,只会出现 2 个新图像。

我试过/猜测问题出在哪里:

滥用我的

useEffect
,它要么来自:

  • 对 removeEventListener 方法的误解,它是否“禁用”了我的 handleKey 函数中的设置坐标?
  • 未指定正确的依赖项 [handleKey]:handleKey 功能由按键激活并更改新坐标。所以每次我通过一个新坐标时重新渲染似乎是正确的
  • VS 代码警告:“'handleKey”函数使 useState Hook 的依赖项在每次渲染时都会发生变化。将它移到 useEffect 回调中。”我确实尝试过,但它不再起作用了。

我的实际代码

import egg from "./logo.png";
import { useState, useEffect } from "react";

function App() {
  let map = []; //array of keys to store
  const [coordinates, setcoordinates] = useState([]); //array of image coordinates

  const handleKey = (event) => {
    onkeydown = onkeyup = function (event) {
      map[event.keyCode] = event.type === "keydown";
    };
    //random image coordinates
    if (map[87] && map[67] && map[78]) {
      const newCoordinates = [...coordinates];
      let random_left = Math.floor(Math.random() * window.innerWidth);
      let random_top = Math.floor(Math.random() * window.innerHeight);
      newCoordinates.push({ left: random_left, top: random_top });
      setcoordinates(newCoordinates);
    }
  };
  useEffect(() => {
    window.addEventListener("keypress", handleKey);
    return () => {
      window.removeEventListener("keypress", handleKey);
    };
  }, [handleKey]);
  return (
    <div className="App">
      <img src={egg} alt="o easter egg" />
      <h1>Rocambole</h1>
      <h2>Good luck!</h2>
      {console.log(coordinates)}
      {coordinates.map((item, index) => {
        return (
          <img
            key={index}
            src={egg}
            alt="egg"
            className="newImg"
            style={{ top: `${item.top}px`, left: `${item.left}px` }}
          />
        );
      })}
    </div>
  );
}

export default App;

javascript html reactjs dom
1个回答
1
投票

尝试用一个函数更新状态,这样你就可以确保注册在内存中的事件监听器每次都获得新鲜的状态,并且还可以将函数

handleKey
移到
useEffect
中:

import egg from "./logo.png";
import { useState, useEffect } from "react";

function App() {
  let map = []; //array of keys to store
  const [coordinates, setcoordinates] = useState([]); //array of image coordinates
  useEffect(() => {
    const handleKey = (event) => {
      onkeydown = onkeyup = function (event) {
        map[event.keyCode] = event.type === "keydown";
      };
      //random image coordinates
      if (map[87] && map[67] && map[78]) {
        let random_left = Math.floor(Math.random() * window.innerWidth);
        let random_top = Math.floor(Math.random() * window.innerHeight);
   
        setcoordinates(coordinates =>[...coordinates, { left: random_left, top: random_top }]);
      }
    };
    window.addEventListener("keypress", handleKey);
    return () => {
      window.removeEventListener("keypress", handleKey);
    };
  }, []);
  return (
    <div className="App">
      <img src={egg} alt="o easter egg" />
      <h1>Rocambole</h1>
      <h2>Good luck!</h2>
      {console.log(coordinates)}
      {coordinates.map((item, index) => {
        return (
          <img
            key={index}
            src={egg}
            alt="egg"
            className="newImg"
            style={{ top: `${item.top}px`, left: `${item.left}px` }}
          />
        );
      })}
    </div>
  );
}

export default App;
© www.soinside.com 2019 - 2024. All rights reserved.