我正在尝试console.log
用户正在键入的html元素。
为此,我实现了以下挂钩:
export const useGetActiveElement = () => {
const [activeElement, setActiveElement] = useState()
useEffect(() => {
if (window){
window.addEventListener('keyup', setCorrectElement);
}
return () => {
window.removeEventListener('keyup', setCorrectElement);
}
}, [])
const setCorrectElement = (element) => {
if(element.target.tagName === 'INPUT' || element.target.tagName === 'TEXTAREA') {
setActiveElement(element.target)
}
}
return activeElement}
export default () => {
const activeElement = useGetActiveElement()
console.log(activeElement) <==== Here! Only prints the value 2 or 3 times...
return <AnotherComponent />
}
出于某种原因,我不明白,该值在控制台中打印了几次,但在某个时候,它不再打印了。
我不确定这是否是Ref的问题。。。但找不到合理的解释。
想法?
感谢
在初始渲染时,钩子的内部状态用undefined
初始化。
当您按下某个键时,您将输入回调并尝试将状态设置为HTML元素。React进行了几次优化尝试,并将旧状态与新状态进行比较。如果值不同,它将安排使用该挂钩的任何组件的重新发布程序。由于undefined
和HTML元素不同,React将导致组件的重新发布,console.log消息将显示当前元素。
当您第二次按键时,您将尝试再次将状态设置为HTML元素。然而,这一次,该值为以前的状态,这意味着使用该状态的以前组件不需要重新提交。
然而,React的并发性有一个已知的怪癖,React实际上会再渲染一次,以确定当前提交的版本。
https://github.com/facebook/react/issues/17474#issuecomment-560942800
我们不知道当前提交了两个版本中的哪一个。当这种模糊性发生时,我们必须进行一次过度渲染,然后我们知道两个版本是相同的,这无关紧要。
因此,您的组件将一次又一次地渲染,您的console.log消息将显示当前元素。
然而,当您第三次按下某个键时,React会再次注意到它是相同的引用,但这次不会重新发送您的组件。
因此,您的组件不会第三次重新发送,您的控制台日志也不会显示。