Skip to content

ref 用来拿到什么? ​

ref 拿到子组件不想放进状态的东西:DOM 节点、命令式组件实例,或一个跨渲染保持的可变值。能用状态和 props 表达的数据,不要绕道 ref。

原理 ​

jsx
const inputRef = useRef(null)
return <input ref={inputRef} />

提交之后 inputRef.current 才是节点。渲染期间第一次是 null。改 current 不会触发渲染。要用它驱动界面,把值放进 state。

类组件可以用 React.createRef,或回调 ref。回调 ref 在节点挂上和卸下时调用,适合节点身份会变的情况。

React 19 里函数组件可以把 ref 当普通 prop。更早的版本要用 forwardRef 把 ref 转给内部 DOM。命令式方法用 useImperativeHandle 只暴露少数几个函数,不要把整个内部状态交出去。

父组件通过 ref 命令子组件滚动、聚焦,是合理的。父组件通过 ref 去改子组件的内部数据,说明状态放错了地方。

追问 ​

ref 和 useRef 保存上一次的值?

可以在渲染时把 state 记到另一个 ref 里,下次渲染读到的是上一轮的值。这是逃逸口,能用派生计算就不要记这份副本。

字符串 ref 呢?

ref="input" 是旧 API,不要用。它挂在类实例上,函数组件没有这个对象。

易错点 ​

  • 在渲染阶段使用 ref.current 的 DOM 做布局判断。那时节点可能还没提交,或者这次渲染不该有副作用。
  • 把频繁变化的值放进 ref 又期望界面更新。
  • 回调 ref 写成内联函数,每次渲染都先以 null 调用再传入节点。需要稳定身份时用 useCallback 或 useRef。

相关 ​