React点击模态框内编辑按钮无法聚焦input、disabled属性移除失效问题
问题根因
- 你调用
setEditState、setActiveButton两个状态更新方法后,会触发组件异步重渲染,你在状态更新后直接操作原生DOM做的修改(移除类名、修改value、切换disabled、调用focus),都会被重渲染后生成的新DOM结构完全覆盖,所以才会出现操作瞬间生效后立刻恢复初始状态的表现。 - 你没有遵循React状态驱动的开发逻辑,直接通过
querySelector操作DOM修改input属性,而没有将input的disabled、value等核心属性绑定到React状态,导致重渲染时属性被JSX的默认配置重置。 - focus操作的时机错误,状态更新后DOM还未完成重渲染,此时调用focus操作的是旧DOM节点,重渲染后节点更新,聚焦状态自然失效。
修复方案
步骤1:用Ref绑定input实例,替换原生DOM查询
// 新增ref存储所有input的引用 const inputRefs = useRef([]);
步骤2:将input的核心属性绑定到React状态
修改input的JSX配置,把disabled、value都和editState绑定,不要手动操作DOM修改:
<input // value绑定到状态,编辑态用editState的值,非编辑态用原始分类名 value={editState?.id === ctg.id ? (editState.value || ctg.name) : ctg.name} // disabled绑定到状态,只有当前分类是编辑态时才取消禁用 disabled={editState?.id !== ctg.id} // 挂载ref到数组对应索引 ref={el => inputRefs.current[key] = el} style={{maxWidth:'180px'}} // 类名也绑定到状态,不用手动增删 className={`categoryInput ${editState?.id === ctg.id ? '' : 'pointer'} ${key}`} onChange={e=>setEditState({ id:ctg.id, value:e.target.value })} onBlur={()=>{ // 失焦直接重置编辑状态,不要手动修改input的值 setEditState(null) }} />
步骤3:修改编辑触发函数,移除原生DOM操作
const editCatName = (e,id)=>{ e.stopPropagation(); const currentCtg = categories[id]; // 只更新状态,DOM修改由React自动完成 setEditState({id: currentCtg.id, value: currentCtg.name}) setActiveButton('editcatname'); }
步骤4:新增useEffect监听编辑状态,重渲染完成后执行聚焦
useEffect(() => { // 编辑状态存在时才执行聚焦 if(editState?.id) { // 匹配对应分类的索引 const targetIndex = categories.findIndex(ctg => ctg.id === editState.id); if(targetIndex > -1 && inputRefs.current[targetIndex]) { inputRefs.current[targetIndex].focus(); } } }, [editState, categories])
注意事项
- 不要在React中直接操作原生DOM修改value、disabled等和渲染相关的属性,所有和视图相关的变化都要通过状态驱动,否则重渲染时会被重置。
- 涉及DOM操作的行为(比如focus)要放到useEffect中,等状态更新、DOM重渲染完成后再执行,才能保证操作生效。
内容的提问来源于stack exchange,提问作者Dayvvo
相关产品推荐
相关产品推荐

