簡體   English   中英

Keyup 事件監聽器不使用 React 中的更新狀態

[英]Keyup event listeners not using the updated states in React

我正在開發一個在線 ide,我必須在其中添加快捷鍵來運行代碼,只需Ctrl + Enter即可執行一段代碼。 我已經完成了添加快捷方式的部分,但主要問題是每當我使用快捷方式時,正在通過的狀態不會更新,而是使用初始狀態。

我試圖在以下代碼中以最接近的方式重現我的情況:

import "./styles.css";
import { useState, useEffect } from "react";

export default function App() {
  let [name, setName] = useState("John Doe");
  useEffect(() => {
    let handleShortcutKeys = (evt) => {
      if (evt.ctrlKey) {
        if (evt.key === "Enter") {
          alert(name);
        }
      }
    };
    window.addEventListener("keyup", handleShortcutKeys);
    return () => {
      window.removeEventListener("keyup", handleShortcutKeys);
    };
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <input
        type="text"
        placeholder="enter something..."
        value={name}
        onChange={(evt) => setName(evt.target.value)}
      />
      <br />
      <br />
      <button onClick={() => alert(name)}>Alert Name</button>
    </div>
  );
}

你可以在這里玩這個片段: https://codesandbox.io/s/event-listener-bug-mcve-u0zvff

這是一個非常基本的代碼,但我不知道到底是什么錯誤,嘗試更改名稱然后,首先嘗試使用按鈕Alert Name然后嘗試按Ctrl + Enter你將能夠看到差異.

提前致謝!

您可以在input中使用onKeyup

import "./styles.css";
import { useState} from "react";

export default function App() {
  const [name, setName] = useState("John Doe");
  const handleShortcutKeys = (evt) => {
    if (evt.ctrlKey) {
      if (evt.key === "Enter") {
        alert(name);
      }
    }
  };
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <input
        type="text"
        placeholder="enter something..."
        value={name}
        onChange={(evt) => setName(evt.target.value)}
        onKeyUp={handleShortcutKeys}
      />
      <br />
      <br />
      <button onClick={() => alert(name)}>Alert Name</button>
    </div>
  );
}

希望這對您有所幫助。

當您注冊事件偵聽器時,它會在此時獲取 state 的值。 並且由於useEffect依賴項是空的,它只會運行一次。 因此您可以簡單地將name依賴項添加到useEffect依賴項中。

  useEffect(() => {
    let handleShortcutKeys = (evt) => {
      if (evt.ctrlKey) {
        if (evt.key === "Enter") {
          alert(name);
        }
      }
    };
    window.addEventListener("keyup", handleShortcutKeys);
    return () => {
      window.removeEventListener("keyup", handleShortcutKeys);
    };
  }, [name]);

或者,您可以將事件處理程序移出useEffect並將其包裝在useCallback掛鈎中

  const handleShortcutKeys = useCallback((evt) => {
    if (evt.ctrlKey) {
      if (evt.key === "Enter") {
        alert(name);
      }
    }
  }, [name])
  
  useEffect(() => {
    window.addEventListener("keyup", handleShortcutKeys);
    return () => {
      window.removeEventListener("keyup", handleShortcutKeys);
    };
  }, [handleShortcutKeys]);

注冊事件偵聽器時,它會選擇在注冊時存在的 state 變量的值。 這就是為什么它總是給你相同的價值。 要修復它,您可以在useEffect依賴數組中添加name ,或使用ref代替 state 變量,如下所示:

import "./styles.css";
import { useState, useEffect, useRef } from "react";

export default function App() {
  const nameRef = useRef("John Doe");
  useEffect(() => {
    const handleShortcutKeys = (evt) => {
      if (evt.ctrlKey) {
        if (evt.key === "Enter") {
          alert(nameRef.current);
        }
      }
    };
    window.addEventListener("keyup", handleShortcutKeys);
    return () => {
      window.removeEventListener("keyup", handleShortcutKeys);
    };
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <input
        type="text"
        placeholder="enter something..."
        defaultValue={nameRef.current}
        onChange={(evt) => {
          nameRef.current = evt.target.value;
        }}
      />
      <br />
      <br />
      <button onClick={() => alert(nameRef.current)}>Alert Name</button>
    </div>
  );
}

沙盒鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM