使用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
相关产品推荐
相关产品推荐

