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
相关产品推荐
相关产品推荐

