[React]受控组件与非受控组件

1. 受控组件(Controlled Component)

定义:

组件的状态(如输入框的值、开关的状态等)完全由父组件通过 props 控制,子组件只负责展示和触发事件,所有数据的"源头"都在父组件。

特点:

  • 组件的 value/checked 等属性由父组件 state 决定。
  • 组件内部通过 onChange 通知父组件,父组件再更新 state,重新传给子组件。
  • 数据流是单向的,便于管理和调试。

你的代码中的例子:

<Input value={editPromoCode} onChange={e => setEditPromoCode(e.target.value)} />

如果 editPromoCode 是父组件 state,通过 props 传进来,这就是受控组件。


2. 非受控组件(Uncontrolled Component)

定义:

组件的状态由自己内部 useState/useRef 管理,父组件无法直接控制组件内部的值。需要时可以通过 ref(关于ref的使用,在下面有更详细的解释) 获取当前值。

特点:

  • 组件内部自己维护 value/checked。
  • 父组件无法直接"控制"组件的值,只能通过 ref 或其他方式"获取"值。
  • 适合表单等"只在提交时收集数据"的场景。

例子:

const [inputValue, setInputValue] = useState(''); <Input value={inputValue} onChange={e => setInputValue(e.target.value)} />

如果 inputValue 只在子组件内部,父组件无法直接拿到,这就是非受控组件。


3. 结合你的代码说明

你现在的写法是受控组件

  • 父组件持有 editPromoCode、editAutoDisplay 的 state。
  • 子组件通过 setEditPromoCode、setEditAutoDisplay 修改父组件 state。
  • 父组件在 save 时直接读取最新 state,提交给后端。

如果你改成非受控组件

  • editPromoCode、editAutoDisplay 只在 PromoCodeButton 内部用 useState 管理。
  • 父组件无法直接拿到最新值,只能通过 ref 或 onChange 在特定时机获取。

4. 受控 vs 非受控 适用场景

  • 受控组件:需要父组件实时感知、联动、校验、统一管理数据时(如表单校验、多个组件联动)。
  • 非受控组件:只在特定时机(如点击保存)收集数据,平时不需要父组件关心内部状态时。

5. 总结

  • 受控组件:数据在父,子只展示和触发事件,适合复杂交互和联动。
  • 非受控组件:数据在子,父只在需要时获取,适合简单表单或弹窗。

你的当前写法是受控组件,适合需要父组件统一管理 promoCode 状态的场景。

-------- 关于上面提到的ref,以及ref是否使用,什么时候使用 --------------

1. 现在的方式(外部 state 传递 editPromoCode、setEditPromoCode、editAutoDisplay、setEditAutoDisplay)

优点:

  • 父组件始终持有最新的编辑态数据,便于统一管理和联动。
  • 适合多个组件间需要共享/联动编辑态数据的场景。
  • 逻辑清晰,数据流单向,易于调试。

缺点:

  • props 变多,组件接口复杂,维护成本上升。
  • 父组件代码臃肿,需管理较多 state。

2. ref方式(子组件内部 state,父组件通过ref获取数据)

优点:

  • props 简洁,组件更内聚,易于复用和维护。
  • 父组件只需在 save 时获取数据,减少无关的 state 管理。
  • 适合"只在特定时机(如save)同步数据"的场景。

缺点:

  • 破坏了 React 的单向数据流,调试时数据流向不如 props 明确。
  • 需要 forwardRef/useImperativeHandle,写法稍复杂。
  • 如果有多个地方需要实时拿到编辑态数据,不如 props 方式灵活。

总结建议

  • 如果你的业务只需要在 save 时同步数据,且不需要父组件实时感知编辑态数据,推荐用 ref 方式,代码更简洁。
  • 如果编辑态数据需要被父组件或其他组件实时感知、联动,建议继续用 props 方式。

实际开发中,ref 方式更适合表单类、弹窗类的"提交时统一收集数据"场景 ,而props 方式更适合全局/多组件联动的复杂场景

因此,大多数情况下,考虑到组件后续的迭代和可维护性,应该优先选择state来进行状态管理。但考虑到过多的props会让组件变的过于冗长,应该在两者中做一个平衡。

相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter9 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js
柳杉10 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化