[英]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.