React中的props、state和ref

React 中三类核心数据来源的职责差异与判断边界。

#tech / dev / frame #resource / react #type / concept #status / growing

[!info] related notes

React中的props、state和ref

很多 React 代码之所以会越写越乱,不是因为组件太多,而是没有分清 propsstateref 各自该管什么。

一句话定义

  • props:外部传入的数据
  • state:组件内部、且会影响渲染的记忆
  • ref:组件内部、但不参与渲染的可变值

props 管什么

  • 父组件给子组件的输入
  • 展示内容、行为配置、回调函数等
  • 本质上是“组件从外界接收什么”

state 管什么

  • 组件自己需要记住的值
  • 这些值变化后会重新影响 UI
  • 通常由 useStateuseReducer 管理

例如:

  • 输入框内容
  • 当前选中项
  • 弹窗是否打开
  • 加载中 / 失败 / 成功状态

ref 管什么

  • DOM 引用
  • 定时器 ID
  • 某个实例对象
  • 上一次渲染值

它们的共同点是:需要记住,但变化后不需要重新渲染界面。

例如:

  • inputRef.current
  • timerRef.current
  • previousValueRef.current
  • 第三方实例对象

一个最实用的判断题

每次面对一个值时,先问三件事:

  1. 它是不是父组件给我的?如果是,多半是 props
  2. 它变化后要不要更新界面?如果要,多半是 state
  3. 它只是想被记住,但不驱动渲染吗?如果是,多半是 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 的内部记忆。

创建于 2026/3/19 更新于 2026/5/27