[英]How to run a function in React when the Escape button has been pressed?
该组件的整个想法是,第一次按下Escape键时,state 中的值confirm
更改为true
以验证用户确实想要执行secPress()
function 并在 5 秒内再次按下Escape键运行secPress()
function。
不幸的是,组件中的secPress()
function 从未运行过。
如何让 function 在第二次按键后运行?
import React, { useState, useEffect, useCallback } from "react";
export function useKeypress(key, action) {
useEffect(() => {
function onKeyup(e) {
if (e.key === key) action();
}
window.addEventListener("keyup", onKeyup);
return () => window.removeEventListener("keyup", onKeyup);
}, []);
}
const App = () => {
const [confirm, setConfirm] = useState(false);
// this function never run
const secPress = () => {
console.log("Double escape pressed");
};
const _confirm = useCallback(() => {
setConfirm((prev) => !prev);
console.log(confirm); // <-- always show false
if (confirm) {
secPress();
}
}, [confirm]);
useKeypress("Escape", _confirm);
useEffect(() => {
const d = setTimeout(() => {
setConfirm(false);
}, 5000);
return () => {
clearTimeout(d);
};
}, [confirm]);
return <>{confirm ? "true" : "false"}</>;
};
export default App;
反应版本:17.0.2
在您的情况下,这是因为您将一个空的依赖项数组传递给 useKeypress function 中的 useEffect; 这样,事件侦听器始终具有相同的回调。
最简单的更改是传递依赖项,例如:
import React, { useState, useEffect, useCallback } from "react";
export function useKeypress(key, action, deps) {
useEffect(() => {
function onKeyup(e) {
if (e.key === key) action();
}
window.addEventListener("keyup", onKeyup);
return () => window.removeEventListener("keyup", onKeyup);
}, deps);
}
const App = () => {
const [confirm, setConfirm] = useState(false);
// this function never run
const secPress = () => {
console.log("Double escape pressed");
};
const _confirm = useCallback(() => {
setConfirm(prev => !prev);
console.log(confirm); // <-- always show false
if (confirm) {
secPress();
}
}, [confirm]);
useKeypress("Escape", _confirm, [confirm]);
useEffect(() => {
const d = setTimeout(() => {
setConfirm(false);
}, 5000);
return () => {
clearTimeout(d);
};
}, [confirm]);
return <>{confirm ? "true" : "false"}</>;
};
export default App;
前面的答案不正确,你不应该在事件监听器效果中添加 [confirm]
工作示例:
https://codesandbox.io/s/00rxv
const [stage, setStage] = useState("initial");
const secPress = () => {
console.log("Double escape pressed");
};
const keydown = (e) => {
if (e.key === "Escape") {
setStage((current) => (current === "initial" ? "confirm" : "success"));
}
};
useEffect(() => {
window.addEventListener("keydown", keydown);
return () => window.removeEventListener("keydown", keydown);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (stage === "success") {
secPress();
}
if (stage !== "confirm") {
return;
}
const d = setTimeout(() => {
setStage("initial");
}, 2000);
return () => {
clearTimeout(d);
};
}, [stage]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.