javascript 无法在react中聚焦输入

t3psigkw  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(163)

我尝试在用户点击Antd标签时(也就是输入框可见时)聚焦Antd标签内的输入框。我使用useImperativeHandle钩子来实现这一点。

父组件

const Parent=()=>{
const threadRef=useRef()
() => {
  const onTabChange = activeKey => {
    if (activeKey === 1 && chatThreadRef.current) {
      chatThreadRef.current.focusInput()
    }
  }
  return (
    <Tabs
      items={[
        { label: 'tab 1', key: 0, children: <>tab 1</> },
        { label: 'tab 2', key: 1, children: <ChildComponent/> },
      ]}
      onChange={onTabChange}
    />
  )
}
}

子组件

const ChildComponent = forwardRed((props,ref) => {
  const [focusableElements, setFocusableElements] = useState([])
  const wrapperRef = useRef(null)
  useEffect(() => {
    const messageInput = wrapperRef.current.querySelector('input')
    setFocusableElements(messageInput)
  }, [])

  useImperativeHandle(ref, () => ({
    focusInput: () => {
      console.log(focusableElements[0])
      focusableElements[0].value = '1'
      focusableElements[0].focus()
    },
  }))
  return (
    <div ref={wrapperRef}>
      <Input className="input" />
    </div>
  )
})

无论何时调用focusInput,代码中的父组件console.log(focusableElements[0])语句都会打印input元素,我也可以将值设置为input,但它不会得到焦点。

nlejzf6q

nlejzf6q1#

看起来你的代码中可能有一个小错误。在调用focus()之前,不要将focusableElements[0]输入元素的value属性设置为“1”,而应该在调用focus()之后设置它。
尝试将子组件中的focusInput函数更改为:

focusInput: () => {
  console.log(focusableElements[0])
  focusableElements[0].focus()
  focusableElements[0].value = '1'
},

这样,输入元素将首先被聚焦,然后其值将被设置为“1”。

vuv7lop3

vuv7lop32#

在父组件的onTabChange中添加console.log("onTabChange in parent")
你应该看到它在你的console.log(focusableElements[0])之前被称为**,而不是之后。
原因有二:

  • 你把setFocusableElements(messageInput)放在useEffect中,因为ref.current需要被渲染。但是它会在onTabChange之后被调用,而onTabChange首先触发了all thing。
  • useEffect将调用setFocusableElements,这将触发childElement的重新渲染。useImperativeHandle将在此重新渲染时使用FocusableElements进行更新,但更改useImperativeHandle不会触发使用ref重新渲染父元素。

解决方案:

focus()应放置在useEffect中。
但是,如果你把这个调用放在父对象中,它将不起作用。子对象的重新渲染不会触发父对象的重新渲染。最好直接把焦点放在子对象上。
我们这里没有关于为什么要这样构建的上下文,但是如果你绝对需要由父对象控制焦点,请使用布尔props:

// In the parent component :
const parent = () => {
   const [willFocus, setWillFocus] = useState(false);
   const onTabChange = activeKey => {
      if (activeKey === 1 && chatThreadRef.current) {
        setWillFocus(true)
      }
   }
   return <Child willFocus={willFocus} />
// In the child component :
const parent = ({willFocus}) => {
   const ref = useRef(null);
   useEffect(() => {
      willFocus && ref.current.focus();
   }, [willFocus]);

   return <input ref={ref} />

相关问题