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

相关推荐
无羡仙19 小时前
替代 Object.freeze 的精准只读模式
前端·javascript
web前端12319 小时前
Java客户端开发指南 - 与Web开发对比分析
前端
龙在天19 小时前
前端 9大 设计模式
前端
搞个锤子哟19 小时前
网站页面放大缩小带来的问题
前端
hj5914_前端新手19 小时前
React 基础 - useState、useContext/createContext
前端·react.js
半花19 小时前
【Vue】defineProps、defineEmits 和 defineExpose
前端·vue.js
霍格沃兹_测试19 小时前
软件测试 | 测试开发 | H5页面多端兼容测试与监控
前端
toooooop819 小时前
本地开发环境webScoket调试,保存html即用
前端·css·websocket
山有木兮木有枝_19 小时前
手动封装移动端下拉刷新组件的设计与实现
前端
阳光阴郁大boy19 小时前
大学信息查询平台:一个现代化的React教育项目
前端·react.js·前端框架