React.js中如何解决useConfirmDialog弹窗内文本输入框输入时失焦问题
问题根因
输入框自动失焦本质是组件被卸载后重新挂载导致的,核心触发点有两处:
useConfirmDialog中返回的Dialog是每次Hook执行时重新定义的函数组件,只要父组件状态更新,React就会将其识别为全新的组件,销毁旧实例并挂载新实例,输入框的焦点自然会丢失。- 传递给
useConfirmDialog的inputArea是内联编写的JSX,每次父组件渲染都会生成新的JSX对象,也会触发弹窗内容的整体重渲染。
修复步骤
1. 修改useConfirmDialog逻辑
不要返回函数组件,直接返回已经渲染完成的React元素,修改Confirmdialog.tsx中的代码:
export const useConfirmDialog = ( props: ConfirmDialogProps ): [() => void, ReactElement] => { const [show, setShow] = useState(false); function toggleDialog() { setShow((show) => !show); } // 直接返回渲染后的元素,不要返回函数组件 const dialog = ( <ConfirmDialogModal key="confirmDialog" {...props} open={show} toggleDialog={toggleDialog} /> ); return [toggleDialog, dialog]; };
2. 调整弹窗渲染方式
原来调用弹窗的写法 <CloneConfirm /> 直接改为 {CloneConfirm} 即可,不需要再加括号执行。
3. 优化重渲染逻辑(可选,进一步避免同类问题)
- 用
useMemo缓存inputArea,仅在依赖变化时重新生成:
const inputArea = useMemo(() => ( <TextInput type="text" id="kc-name" name="name" value={clonedRoleName} onChange={(val) => onChangeHandler({ target: { value: val, name: 'name' }, }) } /> ), [clonedRoleName, onChangeHandler]) const [toggleCloneDialog, CloneConfirm] = useConfirmDialog({ titleKey: 'roles:cloneRole', messageKey: deleteMessage, continueButtonLabel: 'roles:clone', inputArea: inputArea, continueButtonVariant: ButtonVariant.primary, onConfirm: async () => { clone(); }, });
- 用
useCallback缓存onChangeHandler,避免每次渲染生成新的函数实例:
const onChangeHandler = useCallback((event) => { const { value } = event.target; setClonedRoleName(value); }, []);
内容的提问来源于stack exchange,提问作者edile
相关产品推荐
相关产品推荐

