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

相关推荐
sTone873756 分钟前
Android Room部件协同使用
android·前端
晴殇i10 分钟前
前端代码规范体系建设与团队落地实践
前端·javascript·面试
用户740546399430911 分钟前
Vite 库模式输出 ESM 格式时的依赖处理方案
前端·vite
开发者小天18 分钟前
React中使用useParams
前端·javascript·react.js
lichong95126 分钟前
Android studio release 包打包配置 build.gradle
android·前端·ide·flutter·android studio·大前端·大前端++
nvvas40 分钟前
npm : 无法加载文件 D:\nvm\nodejs\npm.ps1,因为在此系统上禁止运行脚本问题解决
前端·npm·node.js
拉不动的猪1 小时前
浏览器之内置四大多线程API
前端·javascript·浏览器
林太白1 小时前
5大排序算法&2大搜索&4大算法思想
前端
摇滚侠1 小时前
浏览器的打印功能,如果通过HTML5,控制样式
前端·html·html5
喵喵侠w1 小时前
uni-app微信小程序相机组件二次拍照白屏问题的排查与解决
前端·数码相机·微信小程序·小程序·uni-app