无法使用 react-hook-form 将表单元素集中在模式打开上

Unable to focus form element on modal open with react-hook-form

我正在尝试解决一个看起来很简单的问题。我想在模式打开后立即聚焦表单元素。

由于 react-hook-form 不提供表单引用的直接句柄,我正在尝试使用 useEffect 挂钩和 react-hook-forms howngrown setFocus 函数但是我一直看到错误:

s.focus is not a function

代码

--> Link to coding sandbox

import { useEffect } from "react";
import { useForm } from "react-hook-form";
import "./styles.css";
import {
  ChakraProvider,
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalFooter,
  ModalBody,
  Button,
  ModalCloseButton,
  useDisclosure
} from "@chakra-ui/react";

export default function App() {
  const { setFocus, register } = useForm();
  const { isOpen, onClose, onOpen } = useDisclosure();

  useEffect(() => {
    if (!isOpen) return;
    setFocus("name");
  }, [setFocus, isOpen]);

  return (
    <ChakraProvider>
      <div className="App">
        <Button onClick={onOpen}>Open</Button>
        <Modal isOpen={isOpen} onClose={onClose}>
          <ModalOverlay />
          <ModalContent>
            <ModalHeader>Modal Title</ModalHeader>
            <ModalCloseButton />
            <ModalBody>
              <input {...register("name")} />
            </ModalBody>
            <ModalFooter>
              <Button colorScheme="blue" mr={3} onClick={onClose}>
                Close
              </Button>
            </ModalFooter>
          </ModalContent>
        </Modal>
      </div>
    </ChakraProvider>
  );
}

阅读 Chakra 文档有一个 prop initialFocusRef,您可以将 ref 传递给您最初要关注的元素

Chakra provides 2 props for this use case:

initialFocusRef: The ref of the component that receives focus when the modal opens.
finalFocusRef: The ref of the component that receives focus when the modal closes.

import { useEffect, useRef } from "react";
import { useForm } from "react-hook-form";
import "./styles.css";
import {
  ChakraProvider,
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalFooter,
  ModalBody,
  Button,
  ModalCloseButton,
  useDisclosure
} from "@chakra-ui/react";

export default function App() {
  const { setFocus, register } = useForm();
  const { isOpen, onClose, onOpen } = useDisclosure();

  const initialRef = useRef();

  useEffect(() => {
    //setFocus("name");
  }, [setFocus, isOpen]);

  return (
    <ChakraProvider>
      <div className="App">
        <Button onClick={onOpen}>Open</Button>
        <Modal isOpen={isOpen} onClose={onClose} initialFocusRef={initialRef}>
          <ModalOverlay />
          <ModalContent>
            <ModalHeader>Modal Title</ModalHeader>
            <ModalCloseButton />
            <ModalBody>
              <input {...register("name")} ref={initialRef} />
            </ModalBody>
            <ModalFooter>
              <Button colorScheme="blue" mr={3} onClick={onClose}>
                Close
              </Button>
            </ModalFooter>
          </ModalContent>
        </Modal>
      </div>
    </ChakraProvider>
  );
}


根据评论更新

默认情况下,Chkra 焦点启用元素,如果您只需将 tabIndex 添加到您的元素并适当地赋予顺序值,那么它就会得到焦点。以前关闭按钮默认是聚焦的,现在在下面的代码中你会注意到我已经给关闭按钮 tabIndex=2 和给输入元素 tabIndex=1 并且它按预期工作。

<ChakraProvider>
      <div className="App">
        <Button onClick={onOpen}>Open</Button>
        <Modal isOpen={isOpen} onClose={onClose}>
          <ModalOverlay />
          <ModalContent>
            <ModalHeader>Modal Title</ModalHeader>
            <ModalCloseButton tabIndex="2" />
            <ModalBody>
              <input tabIndex="1" {...register("name")} />
            </ModalBody>
            <ModalFooter>
              <Button colorScheme="blue" mr={3} onClick={onClose}>
                Close
              </Button>
            </ModalFooter>
          </ModalContent>
        </Modal>
      </div>
    </ChakraProvider>

如果你想通过 ref 使用它,那么你可以检查“How to share ref usage?”,也许它会对你有所帮助。

也许 setFocus 不能 运行 因为首先卸载模态内容(和里面的输入)。

使用 setFocus 的一个简单解决方案是将表单作为一个独立的组件:

const Form = () => {
  const { setFocus, register } = useForm();

  useEffect(() => {
    setFocus("name");
  }, [setFocus]);

  return <input {...register("name")} />;
};

然后将其包含在 modalBody 中。

Fixed sandbox link