UseEffect 中的 UseRef 问题

Posted

技术标签:

【中文标题】UseEffect 中的 UseRef 问题【英文标题】:UseRef issue in UseEffect 【发布时间】:2020-08-09 02:59:35 【问题描述】:

示例是一个功能组件。我正在使用useRef() 挂钩来获取 ref 一个 div 元素。我想在 Example 挂载时附加一个事件监听器到 ref

const Example: React.FC = () => 
  const ref = useRef<htmlDivElement>(null);

  const handleClick = (): void => 
    // mouse click logic
  ;

  useEffect(() => 
    if (ref && ref.current) 
      ref.current.addEventListener('click', handleClick);
    

    return (): void => 
      if (ref && ref.current) 
        ref.current.removeEventListener('click', handleClick);
      
    ;
  , []);

  return (
    <div ref=ref />
  );
;

发生的情况是 refExample 确实挂载时仍然为空。因此,我无法将event listener 附加到它。 替代解决方案是将id 分配给 div 并将事件侦听器直接附加到 DOM 节点我不想真的想要这样做。

任何关于如何将事件侦听器附加到 ref指导都会非常有帮助:)

【问题讨论】:

使用ref添加点击监听的原因是什么? onClick 道具不够吗? 你使用的方式是正确的。添加一个有效的 sn-p:stackblitz.com/edit/react-kkqwwd 你可以为你遇到的问题创建一个演示吗? @NicholasTower 因为将 onClick 属性传递给非交互式元素并不是一个好习惯。 because it's not a good practice to pass onClick prop to non-interactive elements. 说谁? Refs 是那些无法以声明方式做出反应的事情的逃生口。但是 react can 声明式地点击监听器,所以你应该这样做。 @NicholasTower 你可以在这里查看:github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/… 【参考方案1】:

您可以使用onClick 来设置事件。

const Example = () => 
  const handleClick = useCallback(() => 
    // mouse click logic
  , [])

  return (
    <div onClick=handleClick>Hello World</div>
  );
;

但是,如果您想使用 ref,您需要了解一些概念。首先我测试了你的代码,当useEffect被执行时ref就准备好了,因为useEffect是在DOM被绘制之后执行的。

其次,您需要了解钩子的依赖关系,因为在您的代码中,handleClick 是在每个渲染中创建的,但 useEffect 使用的是此函数创建的第一个引用,因此如果您在 handleClick 中使用依赖关系,您可能会遇到问题

最后,我建议您投资useCallback, useState, useRef, useEffectuseReducer 以了解各自的差异和最佳情况。

【讨论】:

【参考方案2】:

您不需要为此提供参考。 React 使用标准的声明式语法支持开箱即用的点击事件。

const Example: React.FC = () => 
  const ref = useRef<HTMLDivElement>(null);

  const handleClick = (): void => 
    // mouse click logic
  ;

  return (
    <div onClick=handleClick />
  );
;

您在 cmets 中提到您尝试这样做的原因是为了使 lint 规则保持沉默。但是使用 ref 并不能解决 linter 指出的问题,它只会使代码变得足够复杂,以至于 linter 无法弄清楚您在做什么,因此没有意识到您的代码具有相同的问题和以前一样。

要解决 lint 问题,请将角色属性添加到 div,以便屏幕阅读器知道此 div 的用途。具体使用哪个角色取决于点击处理程序正在做什么,但最可能的角色可能是“按钮”或“链接”。

return (
  <div onClick=handleClick role="button" />
);

【讨论】:

感谢您分享这些信息。你能帮我吗:***.com/questions/61428958/… ?

以上是关于UseEffect 中的 UseRef 问题的主要内容,如果未能解决你的问题,请参考以下文章

ZF_react hooks useEffect的实现 useRef useImperativeHandle的实现,react整体功能实现完毕

反应 useEffect 和 useRef

反应 useRef / useEffect HTMLCanvasElement 不可分配

如何在 UseEffect 中将事件侦听器添加到 UseRefs

使用 useeffect 和 useref TypeError 时出错:无法读取 null 的属性“getBoundingClientRect”

React useRef 在运行 useEffect 以填充初始状态后返回 null