Next.js useState useEffect useRef 速记

Next.js状态管理三件套速记

一句话速记:

  • useState:保存“会驱动界面”的数据,改了就触发重新渲染。
  • useEffect:做“副作用”(请求、订阅、定时器、操作 DOM)。可清理。
  • useRef:保存“不会触发渲染”的可变值或 DOM 节点,整个生命周期都能拿到。

useState(渲染用数据)

  • 改变 state 会触发重新渲染。
  • 依赖上一次值时,用函数式更新。
const [count, setCount] = useState(0);

// 基础更新
setCount(3);

// 基于上一次值更新(更安全)
setCount(prev => prev + 1);

小贴士:不要直接修改对象/数组,返回新值;复杂初始值可用 useState(() => heavyInit()) 延迟计算。

useEffect(副作用与清理)

  • 什么时候执行:
  • 无依赖:每次渲染后执行。
  • 空依赖 []:只在首次渲染后执行一次。
  • 有依赖 [a, b]:首次+当依赖变化时执行。
  • 返回清理函数:依赖变化或组件卸载前会先执行。
// 首次执行一次 + 卸载时清理
useEffect(() => {
  const id = setInterval(() => console.log('tick'), 1000);
  return () => clearInterval(id); // 清理
}, []);

// 依赖变化时先清理上一次再重建
useEffect(() => {
  document.title = `count = ${count}`;
  return () => { /* 可选清理 */ };
}, [count]);

常见用途:请求/取消、事件监听/移除、定时器/清理、读写 DOM。

useRef(跨渲染持久可变容器)

  • 改 ref.current 不会触发渲染;引用对象本身稳定不变。
  • 两大用途:存任意可变值(定时器 id、缓存、上次值)、拿 DOM 节点。
// 1) 存可变值:定时器 id
const timerIdRef = useRef<number | null>(null);
function start() {
  if (timerIdRef.current) clearTimeout(timerIdRef.current);
  timerIdRef.current = window.setTimeout(() => console.log('done'), 1000);
}

// 2) 拿 DOM:React 挂载时自动赋值 ref.current = 真实 DOM
const divRef = useRef<HTMLDivElement | null>(null);
return <div ref={divRef}>Hello</div>;

// 3) 解决闭包拿旧值:总拿到“最新值”
const latestCount = useRef(count);
useEffect(() => { latestCount.current = count; });

该用谁

  • 需要显示在界面上、改了就应更新界面 → useState
  • 需要在渲染之外与外界交互(请求、订阅、DOM、定时器) → useEffect
  • 需要记住某个值或 DOM,但不想触发渲染/避免闭包问题 → useRef

易错点速查

  • useEffect 依赖别漏,装 eslint-plugin-react-hooks 的 exhaustive-deps。
  • 定时器/订阅要清理;依赖变更会先执行上一次清理。
  • 基于旧 state 计算新值时用函数式更新。
  • 访问 DOM 用 ref.current,不是 ref 本身。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值