如何在React中基于useState状态变量创建不随状态更新的静态变量?
问题根因
你尝试的所有赋值、拷贝方法本身没有问题,问题出在变量的声明时机:只要你把previousName的赋值语句直接放在组件函数体的顶层,每次user状态更新触发组件重渲染时,这行赋值代码都会重新执行,拿到的永远是最新的user.name,所以看起来像是变量和state绑定联动了,和深浅拷贝完全无关。
解决方案
只需要保证previousName只会在组件第一次渲染时赋值一次即可,React函数组件中最常用的实现方式是用useRef存储初始值:useRef的存储值除非手动修改,否则不会随组件重渲染自动更新,也不会触发组件重渲染。
修改后的Edit组件代码
import { useRef } from 'react' function Edit(props) { const [user, setUser] = [props.user, props.setUser]; // 仅组件第一次实例化时赋值一次,后续重渲染不会更新 const previousName = useRef(props.user.name).current; return ( <> <label>Your previous name was: {previousName}</label> <input value={user.name} onChange={(e) => { setUser({ ...user, name: e.target.value }) }} /> </> ); }
你也可以用空依赖的
useMemo实现同样效果:const previousName = useMemo(() => props.user.name, []),不过对于不需要计算的固定初始值,useRef是更轻量的选择。
特殊场景适配
如果父组件的user初始值是异步获取的,第一次渲染Edit组件时props.user.name为空,可以加一层逻辑保证只在第一次拿到有效值时赋值:
import { useRef, useEffect } from 'react' function Edit(props) { const [user, setUser] = [props.user, props.setUser]; const previousNameRef = useRef(''); // 仅第一次拿到非空的name时赋值,后续不再更新 useEffect(() => { if (previousNameRef.current === '' && props.user.name) { previousNameRef.current = props.user.name } }, [props.user.name]) return ( <> <label>Your previous name was: {previousNameRef.current}</label> <input value={user.name} onChange={(e) => { setUser({ ...user, name: e.target.value }) }} /> </> ); }
内容的提问来源于stack exchange,提问作者MrFrenzoid
相关产品推荐
相关产品推荐

