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

React返回const JSX与函数形式时输入框无法保持焦点的原因

React嵌套定义内联组件导致输入框重渲染失焦原因

核心问题本质

每次MyInput组件重渲染时,内部定义的Input箭头函数会生成全新的函数引用,React的diff算法会将其识别为完全不同的组件类型,触发旧DOM卸载、新DOM挂载的完整流程,输入框作为被卸载重建的DOM节点自然会丢失焦点。

两种写法的差异对比

  • 初始写法不存在问题的原因:
    代码中const Input = <input {...props} />是直接创建类型为原生input标签的React元素,重渲染时React识别到元素类型未发生变化,只会对比更新属性,不会重建DOM节点,输入框焦点可以正常保留。
    function MyInput(props) {
      const Input = <input {...props} />
      return <Label>{Input}</Label>
    }
    
  • 修改后写法触发问题的逻辑:
    将Input定义为MyInput内部的箭头函数后,每次MyInput执行重渲染,都会重新创建一个全新的Input函数。JSX中<Input />的组件类型指向这个每次都会变化的函数引用,按照React的diff规则:组件类型引用变化时,会直接销毁该组件对应的全部子DOM节点,重新挂载新组件的节点。旧输入框被销毁、新输入框被挂载,新节点默认不会继承旧节点的焦点状态,就会出现输入中断、必须重新点击激活的现象。
    // 问题代码
    function MyInput(props) {
      // 每次重渲染这里的Input都是全新的函数引用
      const Input = () => <input {...props} />
      return (
        <Label>
          <Input />
        </Label>
      )
    }
    
  • 防抖场景下问题凸显的原因:
    防抖逻辑会在用户停止输入时触发重渲染,刚好卡在两次输入的间隙触发DOM重建,用户下一次输入前就会直接感知到输入框失焦。

修复方案

不要在函数组件内部嵌套定义子组件,两种可落地的修改方式:

  • 直接在返回的JSX中书写原生input元素,或直接将inputReact元素赋值给变量,不包装成内联函数组件
  • 如果需要抽离组件复用逻辑,将Input组件移动到MyInput外层作用域定义,保证组件引用在多次重渲染中保持稳定,通过props传参即可
    // 修复后:Input定义在组件外层,引用稳定
    const Input = (props) => <input {...props} />
    function MyInput(props) {
      return (
        <Label>
          <Input {...props} />
        </Label>
      )
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 05:18:29