要使其像预期的类组件一样正常工作,有3个关键的事情要做。
正如其他人提到的那样,
useEffect您需要添加一个
[]as作为依赖项数组,该数组将仅在
addEventLister函数触发一次。
第二个主要问题是,您没有像在类组件中那样改变功能组件中
pressed数组的 先前状态 ,如下所示:
// onKeyDown eventthis.setState(prevState => ({ pressed: [...prevState.pressed, key],}))// onKeyUp eventthis.setState(prevState => ({ pressed: prevState.pressed.filter(k => k !== key),}))
您需要按以下方式更新功能之一:
// onKeyDown eventsetPressedKeys(previousPressedKeys => [...previousPressedKeys, key]);// onKeyUp eventsetPressedKeys(previousPressedKeys => previousPressedKeys.filter(k => k !== key));
第三件事是
onKeyDown和
onKeyUp事件的定义已移入其中,
useEffect因此您无需使用
useCallback。
上面提到的事情最终解决了这个问题。请找到我所做的以下工作GitHub存储库,它们可以按预期工作:
https://github.com/norbitrial/react-keydown-useeffect-
componentdidmount
如果您更喜欢JSFiddle版本,请在这里找到它:
https://jsfiddle.net/0aogqbyp/
来自存储库的基本部分,完全正常工作的组件:
const KeyDownFunctional = () => { const [pressedKeys, setPressedKeys] = useState([]); useEffect(() => { const onKeyDown = ({key}) => { if (Consts.ALLOWED_KEYS.includes(key) && !pressedKeys.includes(key)) { setPressedKeys(previousPressedKeys => [...previousPressedKeys, key]); } } const onKeyUp = ({key}) => { if (Consts.ALLOWED_KEYS.includes(key)) { setPressedKeys(previousPressedKeys => previousPressedKeys.filter(k => k !== key)); } } document.addEventListener('keydown', onKeyDown); document.addEventListener('keyup', onKeyUp); return () => { document.removeEventListener('keydown', onKeyDown); document.removeEventListener('keyup', onKeyUp); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return <> <h3>KeyDown Functional Component</h3> <h4>Pressed Keys:</h4> {pressedKeys.map(e => <span key={e} className="key">{e}</span>)} </>}
为什么我使用的原因
// eslint-disable-next-line react-hooks/exhaustive-deps了
useEffect,是因为我不想重新连接的事件,每一次一次
pressed或
pressedKeys阵列正在发生变化。
我希望这有帮助!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)