[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会让组件变的过于冗长,应该在两者中做一个平衡。

相关推荐
有事没事实验室10 分钟前
node.js中的path模块
前端·css·node.js·html·html5
十盒半价21 分钟前
TypeScript + React:大型项目开发的黄金搭档
前端·typescript·trae
楚轩努力变强1 小时前
前端工程化常见问题总结
开发语言·前端·javascript·vue.js·visual studio code
鱼樱前端1 小时前
rust基础二(闭包)
前端·rust
菜鸟学Python1 小时前
Python web框架王者 Django 5.0发布:20周年了!
前端·数据库·python·django·sqlite
前端开发爱好者2 小时前
只有 7 KB!前端圈疯传的 Vue3 转场动效神库!效果炸裂!
前端·javascript·vue.js
pe7er2 小时前
RESTful API 的规范性和接口安全性如何取舍
前端·后端
Fly-ping2 小时前
【前端】JavaScript文件压缩指南
开发语言·前端·javascript
未来之窗软件服务3 小时前
免费版酒店押金原路退回系统之【房费押金计算器】实践——仙盟创梦IDE
前端·javascript·css·仙盟创梦ide·东方仙盟·酒店押金系统
拾光拾趣录3 小时前
常见 HTTP 请求头:从“为什么接口返回乱码”说起
前端·http