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

React点击按钮修改输入框值后选中文本需点击两次如何解决?

问题原因

React中setState是异步批量更新的,调用setName('ray')后不会立刻更新state和对应的DOM节点,当前同步代码中的inputRef.current.select()执行时,输入框的value还停留在更新前的值,所以第一次点击没有选中效果。等本轮同步任务执行完成后React才会触发重渲染更新输入框内容,第二次点击时输入框内容已经是更新后的值,才会正常触发选中文本的逻辑。


方案1:使用useEffect监听状态变化,在DOM更新后执行选中逻辑

把选中文本的逻辑绑定到name状态的更新后生命周期,保证每次name更新完成、DOM同步后再执行选中,该方案不会打断React默认的批量更新逻辑,适用范围更广,更推荐使用:

import { useRef, useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [name, setName] = useState('')
  const inputRef = useRef();
  // 新增useEffect监听name变化
  useEffect(() => {
    if(name) { // 可自定义判断条件避免不必要的选中触发
      inputRef.current.select();
    }
  }, [name])

  const editItem = () => {
    setName('ray')
  };
  return (
    <>
      <input
        ref={inputRef}
        type="text"
        value={name}
        placeholder="e.g. eggs"
        onChange={(e)=>setName(e.target.value)}
      />
      <button type="button" className="edit-btn" onClick={editItem}>
        Focus
      </button>
    </>
  );
}

方案2:使用flushSync强制同步刷新状态更新

如果不想额外新增useEffect监听,可以用ReactDOM提供的flushSync强制让状态更新立刻同步刷新DOM,再执行选中逻辑:

import { useRef, useState } from "react";
import { flushSync } from 'react-dom';
import "./styles.css";

export default function App() {
  const [name, setName] = useState('')
  const inputRef = useRef();
  const editItem = () => {
    // 用flushSync包裹状态更新,强制同步刷新
    flushSync(() => {
      setName('ray')
    })
    inputRef.current.select();
  };
  return (
    <>
      <input
        ref={inputRef}
        type="text"
        value={name}
        placeholder="e.g. eggs"
        onChange={(e)=>setName(e.target.value)}
      />
      <button type="button" className="edit-btn" onClick={editItem}>
        Focus
      </button>
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 06:51:09