我对下面使用useRef来存储先前状态值感到困惑。本质上,它如何能够正确显示先前的值。由于useEffect依赖于“value”,我的理解是每次“value”更改(即当用户更新文本框时),它都会将“prevValue.current”更新为新键入的值。
但这并不是看起来正在发生的事情,这种情况下的步骤顺序是什么?
function App() {
const [value, setValue] = useState("");
const prevValue = useRef('')
useEffect(() => {
prevValue.current = value;
}, [value]);
return (
<div>
<input
value={value}
onChange={e => setValue(e.target.value)}
/>
<div>
Curr Value: {value}
</div>
<div>
Prev Value: {prevValue.current}
</div>
</div>
);
}
3条答案
按热度按时间bvpmtnay1#
好吧,虽然这在技术上是可行的,但这是一种令人困惑的方式,当你添加更多的东西时可能会导致bug。它可行的原因是
useEffect
在状态更改后运行,更改ref值不会导致重新渲染。一个更好的方法是在onChange
处理程序中更新ref值。而不是在效果上。但是你发布的代码的工作方式如下:1.最初,两者都为空
1.用户键入内容,通过
setValue
触发状态更改1.这将触发重新呈现,因此
{value}
是新值,但由于ref尚未更新,因此{prevValue.current}
仍然呈现为旧值1.接下来,在渲染之后,效果运行,因为它有
value
作为依赖项。1.但是,由于更改ref值不会触发重新渲染,因此新值不会反映在渲染的内容中
所以一旦上面的步骤完成,那么从技术上讲state值和ref是相同的值,但是,由于ref的改变没有触发重新渲染,它仍然显示旧的ref值。
这显然不是很好,因为如果 something else 触发重新渲染,比如说您有另一个具有连接状态值的输入,那么
{prevValue.current}
将重新渲染为当前{value}
,然后在技术上是错误的,因为它将显示当前值,而不是以前的值。因此,尽管从技术上讲,它可以在这种用例中正常工作,但当您添加更多代码时,它很容易出现bug,而且很难将其完全覆盖
3gtaxfhh2#
https://reactjs.org/docs/hooks-reference.html#useref
useRef
返回一个可变ref对象,该对象的.current属性初始化为传递的参数(initialValue).The returned object will persist for the full lifetime of the component
。useEffect是否在每次渲染后运行?是的!默认情况下,它运行
both after the first render and after every update
因此,它按顺序步骤发生:
kmpatx3s3#
useRef()
用于在连续渲染中保存值。如果要保留过去的值,请将其放入onChange
:这将在
value
的当前状态值被更改之前将其分配给它,并且您将不需要useEffect
钩子。