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

在父组件内定义子组件对React重渲染、挂载/卸载的影响

React 组件重渲染与挂载/卸载问题解析

问题背景

当在父函数组件内部定义子函数组件时,父组件因状态变化触发重渲染,内部的子组件会随之重渲染,还是先卸载再重新挂载?

以提供的代码场景为例:用户在输入框中输入内容时,每次按键后输入框都会失去焦点(React Native中表现为键盘消失)。问题根源被指向Form组件重渲染时Input子函数被重新声明,但需要明确“重新声明”对应的具体组件行为。

代码示例

import { useState } from 'react';

const Form = () => {
  const [values, setValues] = useState(['', '']);

  const onChange = (value, index) => {
    const newValues = [...values];
    newValues[index] = value;
    setValues(newValues);
  };

  const Input = (props) => {
    return <input type='text' {...props} />;
  };

  return (
    <>
      {values.map((value, index) => (
        <Input
          key={index}
          value={value}
          onChange={(e) => onChange(e.target.value, index)}
        />
      ))}
      <button onClick={() => setValues([...values, ''])}>Add</button>
    </>
  );
};

核心解答

每次父组件Form重渲染时,内部的Input函数都会被重新声明——这意味着React会将这个新的Input视为一个完全不同的组件类型。此时React的处理逻辑是:先卸载之前挂载的旧Input组件实例,再挂载新声明的Input组件实例。

正是这个卸载-重新挂载的过程导致了输入框失焦:旧的输入框DOM元素被移除,新的输入框DOM元素被创建,自然丢失了之前的焦点状态。

解决方案

方案1:将子组件移到父组件外部

把Input组件定义在Form组件之外,这样每次Form重渲染时,Input的引用不会改变,React会识别为同一个组件类型,只会触发组件的重渲染(更新props),不会执行卸载和重新挂载操作:

import { useState } from 'react';

const Input = (props) => {
  return <input type='text' {...props} />;
};

const Form = () => {
  const [values, setValues] = useState(['', '']);

  const onChange = (value, index) => {
    const newValues = [...values];
    newValues[index] = value;
    setValues(newValues);
  };

  return (
    <>
      {values.map((value, index) => (
        <Input
          key={index}
          value={value}
          onChange={(e) => onChange(e.target.value, index)}
        />
      ))}
      <button onClick={() => setValues([...values, ''])}>Add</button>
    </>
  );
};

方案2:直接调用函数而非作为组件渲染

将Input作为普通函数直接调用,而不是以组件标签的形式渲染。此时Input返回的input元素会被视为父组件渲染输出的一部分,React只会更新元素的props,不会触发组件的卸载/挂载逻辑:

// 保持Input在Form内部定义不变
return (
  <>
    {values.map((value, index) => (
      {Input({
        key: index,
        value: value,
        onChange: (e) => onChange(e.target.value, index)
      })}
    ))}
    <button onClick={() => setValues([...values, ''])}>Add</button>
  </>
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:08:14