React中的props、state和ref
React 中三类核心数据来源的职责差异与判断边界。
#tech / dev / frame
#resource / react
#type / concept
#status / growing
[!info] related notes
- 所属 MOC: React MOC
- 上位主题: react
- 相关概念: react-use-state, react-use-ref, react-use-context
React中的props、state和ref
很多 React 代码之所以会越写越乱,不是因为组件太多,而是没有分清 props、state 和 ref 各自该管什么。
一句话定义
props:外部传入的数据state:组件内部、且会影响渲染的记忆ref:组件内部、但不参与渲染的可变值
props 管什么
- 父组件给子组件的输入
- 展示内容、行为配置、回调函数等
- 本质上是“组件从外界接收什么”
state 管什么
- 组件自己需要记住的值
- 这些值变化后会重新影响 UI
- 通常由
useState或useReducer管理
例如:
- 输入框内容
- 当前选中项
- 弹窗是否打开
- 加载中 / 失败 / 成功状态
ref 管什么
- DOM 引用
- 定时器 ID
- 某个实例对象
- 上一次渲染值
它们的共同点是:需要记住,但变化后不需要重新渲染界面。
例如:
inputRef.currenttimerRef.currentpreviousValueRef.current- 第三方实例对象
一个最实用的判断题
每次面对一个值时,先问三件事:
- 它是不是父组件给我的?如果是,多半是
props - 它变化后要不要更新界面?如果要,多半是
state - 它只是想被记住,但不驱动渲染吗?如果是,多半是
ref
为什么这件事特别重要
很多 React 代码越写越乱,不是因为 Hook 太多,而是因为把三种不同角色混到了一起。
典型错误有:
- 本该直接从
props读取,却又复制一份到state - 本该进入
state的值,被偷偷塞进ref - 本该放在普通局部变量里的临时值,被误建成
state
一个常见反例
function UserCard({ user }: { user: { name: string } }) {
const [name, setName] = useState(user.name)
return <div>{name}</div>
}
如果这里只是展示 user.name,那这份 state 很可能是多余的。因为它把外部输入复制成了内部状态,后续同步边界会变复杂。
常见误区
- 把本该进
state的数据藏进ref - 把只用于内部临时计算的值提升成
state - 直接修改
props
最短记忆方式
props 是输入,state 是会驱动 UI 的内部记忆,ref 是不会驱动 UI 的内部记忆。