我正在尝试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问题...但是找不到合理的解释。
想法?
谢谢
答案 0 :(得分:0)
在初始渲染中,钩子的内部状态用undefined
初始化。
当您按下一个键时,您将输入回调并尝试将状态设置为HTML元素。 React进行了几次优化尝试,并将旧状态与新状态进行比较。如果值不同,它将计划重新渲染使用此挂钩的任何组件。由于undefined
和HTML元素不同,因此React将导致您的组件重新呈现,并且console.log消息将显示当前元素。
第二次按下一个键时,您将尝试再次将状态设置为HTML元素。但是,这次,此值作为先前状态,这意味着使用此状态的先前组件无需重新渲染。
但是,React的并发性存在一个已知的怪癖,React实际上会再花一点时间来确定当前提交的版本。
https://github.com/facebook/react/issues/17474#issuecomment-560942800
我们并不便宜地知道当前已提交两个版本中的哪个版本。当这种歧义发生时,我们必须一次渲染一次,此后我们知道两个版本相同并且没关系。
因此,您的组件将第二次渲染,您的console.log消息将显示当前元素。
但是,当您第三次按下一个键时,React会再次注意到它是相同的参考,但是这次不会重新渲染您的组件。
因此,您的组件将不会第三次重新呈现,并且控制台日志也不会显示。