在useEffect中反应Hooks + window.addEventListener

时间:2020-07-18 21:11:46

标签: reactjs react-hooks use-effect

我正在尝试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问题...但是找不到合理的解释。

想法?

谢谢

1 个答案:

答案 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会再次注意到它是相同的参考,但是这次不会重新渲染您的组件。

因此,您的组件将不会第三次重新呈现,并且控制台日志也不会显示。