You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useEffect与useRef实现历史值展示的原理疑问

为什么这段useRef+useEffect的代码能正确记录历史输入值?

咱们一步步拆解这个组件的执行流程,就能搞清楚其中的逻辑:

1. 初始渲染阶段

  • useState初始化name为空字符串"",useRef初始化prevName.current也为""
  • 页面渲染后显示:my name is and it used to be
  • 初始渲染完成后,useEffect触发,把prevName.current设为当前的name(也就是""),这一步暂时看不出变化

2. 第一次输入内容(比如输入"A")

  • 输入框onChange触发setName("A"),这会让组件触发重渲染
  • 重渲染时:
    • useState返回更新后的name值"A"
    • useRef不会重新初始化,prevName还是之前的引用,它的current属性依然是上一轮的""
    • 此时执行return里的UI渲染,页面显示:my name is A and it used to be
  • 重渲染完成后,useEffect因为依赖项name从""变成了"A",所以触发执行,把prevName.current更新为"A"

3. 第二次输入内容(比如输入"B")

  • 同样,onChange触发setName("B"),组件重渲染
  • 重渲染时:
    • name更新为"B",但prevName.current还停留在上一轮的"A"(因为useEffect要等重渲染完成才会执行)
    • 页面渲染显示:my name is B and it used to be A
  • 重渲染完成后,useEffect再次触发,把prevName.current更新为"B"

核心关键点

  • React的重渲染流程是:先计算并渲染新的UI(执行return部分),再执行useEffect里的代码
  • useRef的current属性是可变的,而且在组件整个生命周期里保持同一个引用,不会因为重渲染被重置,所以能稳定保存上一轮的状态值
import React, { useState, useEffect, useRef } from "react";

export default function App() {
  const [name, setName] = useState("");
  const prevName = useRef("");
  useEffect(() => {
    prevName.current = name;
  }, [name]);
  return (
    <>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <div>
        my name is {name} and it used to be {prevName.current}
      </div>
    </>
  );
}

内容的提问来源于stack exchange,提问作者Grease

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:46:26