React Use-Hook-Form setFocus 不设置 Bootstrap Accordions 之间的焦点

问题描述 投票:0回答:3

我们有一个包含 3 个部分的表格,并且要求用户按照下图所示的特定顺序填写此表格(1. 来自 Bin,2. Item,3. To Bin)。在一个部分中输入所需信息后,下一个部分应自动出现,并将焦点放在第一个输入上。这 3 个部分只是 1 个 React-hook-form 的一部分。

但是,我们注意到,当我们更改部分时,react-hook-form 的

setFocus
函数不会将焦点设置在第一个输入上,并且我们似乎无法确定这是为什么或如何使其这样做。我见过一些 setTimeout hack,但这似乎不是正确的方法。

这是一个简单的 codesandbox,我们放在一起来复制这个问题。

对此的任何帮助将不胜感激!

reactjs react-bootstrap react-hook-form
3个回答
1
投票

这里有一个使用 TypeScript、React 和 MaterialUI's Accordion 的解决方案。打开手风琴元素会将焦点转移到其输入元素。

@Igor Gonak 是正确的;根本原因是

focus()
方法对未显示的 DOM 元素不执行任何操作。您必须延迟调用
focus()
,直到手风琴组件呈现之后。您可以使用
setTimout()
(更简单,请参阅下面的输入一)或使用触发渲染后效果的状态标志(输入二)来做到这一点。

import "./styles.css";
import { Accordion, AccordionDetails, AccordionSummary } from "@mui/material";
import { ExpandMore } from "@mui/icons-material";
import { SyntheticEvent, useEffect, useRef, useState } from "react";

export default function App() {
  const ref1 = useRef<HTMLInputElement>(null);
  const ref2 = useRef<HTMLInputElement>(null);

  const [focus, setFocus] = useState(false);

  useEffect(() => {
    if (focus) {
      setFocus(false);
      ref2.current?.focus();
    }
  }, [focus]);

  return (
    <div className="App">
      <Accordion
        onChange={(_: SyntheticEvent, expanded: boolean) => {
          if (expanded) {
            setTimeout(() => ref1.current?.focus(), 100);
          }
        }}
      >
        <AccordionSummary expandIcon={<ExpandMore />}>One</AccordionSummary>
        <AccordionDetails>
          <input ref={ref1} placeholder="Input one" />
        </AccordionDetails>
      </Accordion>
      <Accordion
        onChange={(_: SyntheticEvent, expanded: boolean) => {
          if (expanded) {
            setFocus(true);
          }
        }}
      >
        <AccordionSummary expandIcon={<ExpandMore />}>Two</AccordionSummary>
        <AccordionDetails>
          <input ref={ref2} placeholder="Input two" />
        </AccordionDetails>
      </Accordion>
      <input placeholder="Input three" />
    </div>
  );
}

0
投票

我只能为您指出正确的方向 - 这个问题是因为手风琴项目被隐藏了。如果我通过设置 activeKey 来展开它们,然后浏览输入,它就可以工作。 Accordion.Body 折叠时显示=无,并且您无法聚焦隐藏元素。

当我在 useEffect 中设置焦点时,在 activeIndex 更改后,我认为它可以解决这个问题,但这并没有解决问题:

  useEffect(() => {
    if (activeSection === 1) {
      setFocus("itemID");
    }
    if (activeSection === 2) {
      setFocus("binTo");
    }
  }, [activeSection, setFocus]);

也没有重新渲染,这可能会导致失去焦点。


0
投票

我的猜测是手风琴组件本身尚未完成渲染,因此在手风琴完全渲染之前调用了 setFocus 。添加超时可能会有所帮助。

  useEffect(() => {
    if (isAccordionOpen) {
      setTimeout(() => {
        setFocus("imageUrl");
      }, 50);
    }
}, [isAccordionOpen]);
© www.soinside.com 2019 - 2024. All rights reserved.