React中点击按钮后输入框首次无法获取焦点问题求助
问题:点击按钮后Input首次无法获得焦点,后续操作正常
点击"Enable Input"按钮后,对应的input元素首次无法获得焦点,但再次点击按钮时可以正常聚焦。
原因分析
React的状态更新是异步批量处理的。在按钮点击的回调函数中,调用setInput1("")和setConfig(...)后,组件不会立刻重新渲染,此时input仍然处于disabled={true}的状态,直接调用ref1.current.focus()会因为元素处于禁用状态而失效。当后续点击按钮时,状态已经完成更新,input不再禁用,所以focus操作能正常生效。
解决方案
方法1:使用useEffect监听状态变化
通过useEffect监听config中对应项的变化,当状态更新为允许输入(即config1/config2变为false)时,执行focus操作:
import React, { useEffect, useRef, useState } from "react"; import { render } from "react-dom"; import * as data from "./messages.json"; const App = () => { return <Test {...{ alreadySetVal1: true, alreadySetVal2: true }} />; }; const Test = ({ alreadySetVal1, alreadySetVal2 }) => { const [input1, setInput1] = useState(alreadySetVal1 ? "Already Set" : ""); const [input2, setInput2] = useState(alreadySetVal2 ? "Already Set" : ""); const [config, setConfig] = useState({ config1: !!input1, config2: !!input2 }); const ref1 = useRef(null); const ref2 = useRef(null); // 监听config1变化,完成渲染后聚焦input1 useEffect(() => { if (!config.config1 && ref1.current) { ref1.current.focus(); } }, [config.config1]); // 监听config2变化,完成渲染后聚焦input2 useEffect(() => { if (!config.config2 && ref2.current) { ref2.current.focus(); } }, [config.config2]); return ( <> <div> <input disabled={config.config1} value={input1} ref={ref1} type={config.config1 ? "text" : "password"} onChange={(e) => setInput1(e.target.value)} /> <span onClick={() => { setInput1(""); setConfig({ ...config, config1: false }); }} > Enable Input 1 </span> </div> <div> <input disabled={config.config2} value={input2} ref={ref2} type={config.config2 ? "text" : "password"} onChange={(e) => setInput2(e.target.value)} /> <span onClick={() => { setInput2(""); setConfig({ ...config, config2: false }); }} > Enable Input 2 </span> </div> </> ); }; render(<App messages={data.messages} />, document.getElementById("root"));
方法2:使用setTimeout延迟执行focus
利用setTimeout让React完成状态更新和渲染后再执行focus操作:
// 修改按钮点击回调部分示例 onClick={() => { setInput1(""); setConfig({ ...config, config1: false }); setTimeout(() => { ref1.current?.focus(); }, 0); }}
两种方法都能解决首次点击无法聚焦的问题,推荐使用方法1,因为它更符合React的状态更新机制,避免依赖定时器的不确定性。
内容的提问来源于stack exchange,提问作者user16860065
相关产品推荐
相关产品推荐

