You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用React useRef实现AntDesign Popover打开时内部TextArea自动聚焦

问题根因

你调用focus()无效的核心原因是:setFootnotePopoverVisible是React异步状态更新,状态变更后Popover的内容DOM挂载、入场动画执行都需要时间,你在onVisibleChange里同步调用focus()时,TextArea对应的DOM节点还没完成挂载/渲染到可交互状态,所以focus请求会被浏览器忽略。
另外autoFocus属性仅在元素首次挂载时生效,后续Popover复用DOM节点重新打开时不会触发二次自动聚焦,这也是为什么首次打开正常、后续打开失效。


可行解决方案

方案1:延迟触发focus(最简单通用)

用setTimeout等待Popover完成DOM渲染和动画后再执行聚焦,100ms的延迟足够覆盖大部分场景的动画时长:

function handleFootnoteVisibleChange (visible) {
  setFootnotePopoverVisible(visible);
  if (visible) {
    setTimeout(() => {
      inputRef.current?.focus();
    }, 100);
  }
}

方案2:用requestAnimationFrame避免硬编码延迟

如果不想设置固定延迟,可以嵌套两层requestAnimationFrame确保在DOM更新完成后执行聚焦,逻辑更严谨:

function handleFootnoteVisibleChange (visible) {
  setFootnotePopoverVisible(visible);
  if (visible) {
    // 两层requestAnimationFrame确保DOM已完成重渲染
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        inputRef.current?.focus();
      });
    });
  }
}

可选优化

如果组件频繁重渲染导致Popover内容反复重建,可以用useMemo缓存footnoteContent,减少不必要的DOM更新:

const footnoteContent = useMemo(() => (
  <Form form={form}>
    <Form.Item name={`${cellData.key}-fn`} initialValue={initialValue}>
      <Tooltip placement="left" title="按Ctrl+Enter关闭窗口">
      <Input.TextArea
        disabled={disabled}
        bordered={false}
        autoComplete="off"
        style={{ width: "300px" }}
        autoSize={{ minRows: 4 }}
        placeholder="请输入脚注"
        onBlur={() => save(cellData.key, form.getFieldValue(`${cellData.key}-fn`))}
        onKeyDown={handleKeyDown}
        autoFocus={true}
        ref={ref => { inputRef.current = ref; }}
      />
      </Tooltip>
    </Form.Item>
  </Form>
), [cellData.key, initialValue, disabled, save, handleKeyDown, form])

内容的提问来源于stack exchange,提问作者CJH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 07:54:07