首页 > 解决方案 > 使用 useRef 聚焦元素,将类迁移到 hooks 问题?

问题描述

有谁知道如何使用反应挂钩传递回调引用的正确方法。我正在尝试将内置在类组件中的模态转换为钩子组件,但我不确定正确的方法是什么。

  onOpen = () => {
   this.setState({ isOpen: true }, () => {
    // Ref for the button
    this.closeButtonNode.focus();
   });
   this.toggleScrollLock();
  };

这就是我在代码中传递引用的方式

     <ModalContent
      buttonRef={(n) => {
        this.closeButtonNode = n;
      }}
      {// More props...}
    />

并且模态内容组件具有这样的buttonRef

         <button
          type="button"
          className="close"
          aria-labelledby="close-modal"
          onClick={onClose}
          ref={buttonRef}
        >
          <span aria-hidden="true">×</span>
        </button>

因此,当模式弹出时,我能够通过钩子将焦点集中在我的按钮关闭上,我设法复制行为的唯一方法是添加一个 useEffect 钩子来监听 isOpen 状态,如下所示:

useEffect(() => {
 if (isOpen) closeButtonNode.current.focus();
}, [isOpen]);

const onOpen = () => {
 setIsOpen(true);
 toggleScrollLock();
};

这就是我传递道具的方式

  const closeButtonNode = useRef(null);
  return (
  <ModalContent
    buttonRef={closeButtonNode}
    {// More props...}
  />
  )

而且我只是像普通的 ref 一样使用它,没有传递回调函数,这是可行的,但我想知道为什么它会这样工作,以及为什么我不能像基于类的组件那样将焦点设置在 onOpen 函数上。

如果您想检查完整代码,这是沙箱。 https://codesandbox.io/s/hooks-modal-vs-class-modal-bdjf0

标签: javascriptreactjsreact-hooks

解决方案


为什么我不能onOpen像基于类的组件那样将焦点放在功能上

因为当onOpen函数open仍然被调用时false,它会在模式已经打开后更新。请注意,useState没有第二个参数(回调),就像setState您在基于类的组件中设置焦点时所做的那样。这就是为什么你需要使用useEffect.

您可以通过设置延迟使用setTimeoutafter 你设置open为 true 来测试它,如下所示:

const onOpen = () => {
  setIsOpen(true);
  setTimeout(() => closeButtonNode.current.focus())
};

虽然,您使用的方法useEffect可能是更好的选择。

代码沙盒示例。


推荐阅读