自定义钩子没有正确使用 useState()? [英] Custom hook not using useState() properly?
问题描述
我正在尝试制作其中一个自定义 useKeyPress 挂钩,并且我希望我的 keydown 处理程序在每次按下按钮时触发,即按住某个键不会触发它一百万次.我试图通过有一个标志来指示是否调用处理程序 callHandler
- 它应该只在目标键被释放/组件刚刚安装时设置为 true.以下是我正在尝试做的简化版本:
const useKeyPress = (target)=>{const [callHandler, setCallHandler] = useState(true);const keyDown = (e) =>{if(e.key === target && callHandler){setCallHandler(false);//这条线似乎永远无法正常工作???console.log(callHandler, setCallHandler);//调用keyDown处理程序}}const keyUp = (e)=>{if(e.key === 目标)setCallHandler(true);}useEffect(()=>{document.addEventListener('keydown', keyDown);document.addEventListener('keyup' keyUp);返回 ()=>{document.removeEventListener('keydown', keyDown);document.removeEventListener('keyup', keyUp);}},[]);}useKeyPress('a');
我的问题是 callHandler 从未设置为 false.当我按住a"键时,setCallHandler 之后的控制台日志只是用 (true, ...) 向调试屏幕发送垃圾邮件,这意味着尽管运行 callHandler 的代码块在某种程度上总是错误的.关于为什么这不起作用的任何想法?
我不确定我是否做对了,无论如何我制作了这段代码希望对你有所帮助.
编辑
将其更改为自定义钩子示例,可能对将来的某个人有用.
const useKeyEvent = (target) =>{const [keyTarget,setKeyTarget] = React.useState(target);const [playedKey,setPlayedKey] = React.useState(null);const [keyDone,setKeyDone] = React.useState(false);const keyUp = (e) =>{setPlayedKey(null);设置键完成(假)};const keyDown = (e) =>{const key = e.key;if (key !==playedKey) {if(key === keyTarget){设置键完成(真);}setPlayedKey(key);}};React.useEffect(() => {document.addEventListener("keydown", keyDown);document.addEventListener("keyup", keyUp);返回 () =>{document.removeEventListener("keydown", keyDown);document.removeEventListener("keyup", keyUp);};}, [keyUp, keyDown,keyDone]);返回 [playedKey,keyTarget,setKeyTarget,keyDone];}const App = () =>{const [playedKey,keyTarget,setKeyTarget,keyDone] = useKeyEvent("a");返回 (<div><h3 style={{color:keyDone?"green":"black"}}>按{keyTarget}键!密钥:{playedKey}</h3><input type="text" onChange={(e)=>setKeyTarget(e.currentTarget.value)} maxLength="1" value={keyTarget}/>
)}ReactDOM.render(
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script><div id="react"></div>
I'm trying to make one of those custom useKeyPress hooks, and I want my keydown handler to fire on every individual button press, i.e. holding down a key won't trigger it a million times. I'm trying to do this by having a flag that indicates whether to call the handler, callHandler
- it should only be set to true when the target key is released/the component just mounted. Below is a simplified version of what I'm trying to do:
const useKeyPress = (target)=>{
const [callHandler, setCallHandler] = useState(true);
const keyDown = (e) =>{
if(e.key === target && callHandler){
setCallHandler(false); //This line never seems to work properly???
console.log(callHandler, setCallHandler);
//call the keyDown handler
}
}
const keyUp = (e)=>{
if(e.key === target)
setCallHandler(true);
}
useEffect(()=>{
document.addEventListener('keydown', keyDown);
document.addEventListener('keyup' keyUp);
return ()=>{
document.removeEventListener('keydown', keyDown);
document.removeEventListener('keyup', keyUp);
}
},[]);
}
useKeyPress('a');
My issue is that callHandler is never set to false. That console log immediately after setCallHandler just spams the debug screen with (true, ...) when I hold down the 'a' key, meaning that despite the code block running callHandler is somehow always false. Any ideas as to why this isn't working?
Im not sure if i get it right , anyway i made this code hope helps u a bit.
EDIT
Change it to custom hook example, maybe useful for someone in future.
const useKeyEvent = (target) =>{
const [keyTarget,setKeyTarget] = React.useState(target);
const [playedKey,setPlayedKey] = React.useState(null);
const [keyDone,setKeyDone] = React.useState(false);
const keyUp = (e) => {
setPlayedKey(null);
setKeyDone(false)
};
const keyDown = (e) => {
const key = e.key;
if (key !== playedKey) {
if(key === keyTarget){
setKeyDone(true);
}
setPlayedKey(key);
}
};
React.useEffect(() => {
document.addEventListener("keydown", keyDown);
document.addEventListener("keyup", keyUp);
return () => {
document.removeEventListener("keydown", keyDown);
document.removeEventListener("keyup", keyUp);
};
}, [keyUp, keyDown,keyDone]);
return [playedKey,keyTarget,setKeyTarget,keyDone];
}
const App = () => {
const [playedKey,keyTarget,setKeyTarget,keyDone] = useKeyEvent("a");
return (
<div>
<h3 style={{color:keyDone?"green":"black"}}>Press {keyTarget} key ! Key : {playedKey}</h3>
<input type="text" onChange={(e)=>setKeyTarget(e.currentTarget.value)} maxLength="1" value={keyTarget}/>
</div>
)
}
ReactDOM.render(<App/>, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
这篇关于自定义钩子没有正确使用 useState()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!