自定义钩子没有正确使用 useState()? [英] Custom hook not using useState() properly?

查看:44
本文介绍了自定义钩子没有正确使用 useState()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作其中一个自定义 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(, 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>

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆