简体   繁体   English

UseRef 存储以前的值,但 useRef 的计数器使用当前值

[英]UseRef stores previous value but counter of useRef works with current value

I have one doubt regarding the useRef functionality.我对 useRef 功能有一个疑问。 We know useEffect will update the value after render and useRef does not cause re-renders.我们知道 useEffect 会在渲染后更新值,而 useRef 不会导致重新渲染。 So, value is updated one cycle late and so when we try to display any value in DOM useRef variable, it shows previous value and this becomes a major use case for useRef but then how does update count works fine and shows current value and not one cycle late?因此,值晚了一个周期更新,因此当我们尝试在 DOM useRef 变量中显示任何值时,它显示以前的值,这成为 useRef 的主要用例,但是更新计数如何正常工作并显示当前值而不是一个周期晚了?

import React from "react";
import "./App.css";
import { useEffect, useState, useRef } from "react";

function App(){

const count = useRef(0);
const text = useRef("");
const [inputValue, setInputValue] = useState("");

useEffect(() => {
    text.current = inputValue;
    count.current = count.current + 1;
});

return (
    <>
      <input type="text" value={inputValue} onChange={(e)=>setInputValue(e.target.value)} />
      <h1>Render Count: {count.current}</h1> //displays 1 after re-rende
      <h1>{text.current}</h1> //displays "" after re-render
    </>
  );
}

The count variable runs with current value and not one cycle late.计数变量以当前值运行,而不是延迟一个周期。 Which means after I type a letter "A" in textbox, count.current becomes 1 from 0 and displays 1 but text.current displays previous value ie "" and not "A. Why?这意味着在我在文本框中键入字母“A”后,count.current 从 0 变为 1 并显示 1,但 text.current 显示以前的值,即“”而不是“A”。为什么?

The count should have also run 1 cycle later and should have displayed 1 after 2nd re-render instead of 1st re-render.计数也应该在 1 个周期后运行,并且应该在第 2 次重新渲染而不是第 1 次重新渲染后显示 1。

Because when the component isMounted at the first rendering, the value of counter.current becomes 1 , but the value of text.current is still "" .因为第一次渲染时组件 isMounted 时, counter.current的值变成了1 ,但是text.current的值仍然是"" If you want to make them synchronized do not increase the value of counter.current at the first calling of useEffect callback, cause there is not any changes occured in the input field at that time.如果你想让它们同步,请不要在第一次调用useEffect回调时增加counter.current的值,因为此时input字段没有发生任何变化。

Define a useRef controlling whether the component isMounted or isUpdated like this:定义一个useRef控制组件是已安装还是已更新,如下所示:

const isMounted = useRef(false); 

And then change the useEffect callback:然后更改useEffect回调:

useEffect(() => {
  if(isMounted.current){
    text.current = inputValue;
    count.current = count.current + 1;
  }
  else{
    isMounted.current = true;
  }
});

This time you can see, both of counter.current and text.current are one behind the current changes and they are synchronized together.这次可以看到, counter.currenttext.current都落后于 current 的变化,而且是一起同步的。

By the way always track an input changes with state hook not ref hook .顺便说一下,始终使用state 钩子而不是ref 钩子跟踪输入变化。

I think the root core is two things below:我认为根本核心是以下两件事:

  1. Firstly, useEffect hook is triggered after rendering or re-rendering so the code in useEffect hook will be updated later首先useEffect hook是在渲染或重新渲染后触发的, useEffect hook中的代码稍后会更新
  2. text.current = inputValue means it has reference to inputValue , so when inputValue has latest value, text.current has the new value at the same time. text.current = inputValue 表示它引用了inputValue ,所以当inputValue有最新值时, text.current有新值。 This process happens in onChange event and before useEffect .这个过程发生在onChange事件和useEffect之前。

It leads to text.current has latest value, count.current hasn't它导致text.current有最新的价值, count.current没有

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM