在写React的时候,useState和useRef是两个常见的hook。它们都能让函数组件"记住"一些数据,但作用场景和机制完全不同。这篇文章我们就来详细讲解什么时候用 useState,什么时候用 useRef。
useState是什么
useState 是 React 提供的一个 状态 Hook ,允许你在函数组件中定义响应式的状态。
当 state 发生变化时,React 会重新渲染组件 ,以保证UI 和状态保持一致。
用法示例
jsx
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>点击次数:{count}</p>
<button onClick={() => setCount(count + 1)}>点我+1</button>
</div>
);
}
每次点击按钮,count 更新,React 会触发组件重新渲染,页面上的数字随之变化。
使用场景
-
管理 UI 相关的状态:例如计数器、弹窗开关、表单输入值等。
-
需要驱动渲染的变量:只要这个值变了,UI 就必须更新。
useRef是什么
如果我们希望组件记住一些信息,但 不希望触发重新渲染 ,可以使用 useRef。
useRef 返回一个对象,只有一个属性:current。
你可以把任何值存在 current 里,并在渲染之间保留它。
和 useState 不同的是:修改 ref.current 并不会引起组件重新渲染。
用法
jsx
import { useRef } from 'react';
export default function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>聚焦输入框</button>
</>
);
}
👉 ref={inputRef} 让 React 把这个 <input> 的 DOM 节点放进了 inputRef.current,所以我们就能调用它的原生方法 .focus()。
使用场景
- 操作 DOM 元素
- 聚焦输入框
- 滚动到某个区域
- 手动触发播放/暂停等
- 存储副作用中的变量
-
保存
setInterval的定时器 ID,避免放到state里导致无意义的渲染。iniconst timerRef = useRef(null); timerRef.current = setInterval(...); clearInterval(timerRef.current);
- 保存上一次的值
- 例如对比本次和上次的股票价格,判断涨跌。
- 这样不会影响渲染,但可以在逻辑里取到历史数据。
useState 和 useRef的区别
| 特性 | useState | useRef |
|---|---|---|
| 是否触发重新渲染 | ✅ 会 | ❌ 不会 |
| 返回值 | [state, setState] | { current: value } |
| 使用场景 | 用于 UI 状态 | 保存 DOM、存储副作用变量 |
| 修改方式 | 必须通过 setState | 直接改 current |
| 生命周期 | 组件每次渲染都会更新 | 渲染间隔中值保持不变 |