useRef

Time:2022-6-25

Let’s take a look at how the official website explains:

You should be familiar with ref, the main way to access dom. If you set the ref object to<div ref={myRef} />If the form is passed into the component, react will change the.currentProperty to the corresponding DOM node.
Useref returns a mutable ref object whose The current property is initialized to the passed in parameter (initialvalue). The returned ref object persists throughout the life cycle of the component
What it creates is a normal JavaScript object. Useref() and create a {current:…} The only difference between objects is that useref returns the same ref object each time it is rendered.

The explanation on the official website can be summarized as follows:

  1. Assigned to DOMrefProperty that can be used to access the DOM node
  2. Returns a mutable ref object that has only a current attribute and the initial value is the passed in parameter (initialvalue).
  3. The returned ref object remains unchanged throughout the life cycle of the component
  4. When the current value is updated, it does not re render, which is different from usestate
  5. Useref is similar to this of a class component

About point 1

Let’s first look at how to use useref to obtain DOM nodes

import { useRef} from "react";
import * as ReactDOM from "react-dom";

function App() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    //`current` points to a text input element that is mounted on the DOM
    inputEl.current.focus();
    // inputEl.current.value = 'abc';
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
useRef

GIF 2021-12-14 17-32-31.gif

When I click the button on the right, the input box on the left is focused.

About points 3 and 4

There are the following scenarios: This is an autocomplete component I wrote,handleChangeIt is an event function that triggers search by changing the value of value during normal input,handleSelectThe function is to insert the list value into the input box after I click one of the items in the search results list, but this operation also changes the value of value, resulting in triggering the search – obviously this search is unnecessary. At this time, I try to use a state as an identifier (flag). When normal input (executionhandleChange)Set it to true when clicking the list (executehandleSelect)Set it to false, and then judge whether to perform search according to its value in useeffect. There is no problem with this solution, which is enough to solve my problem. However, we know that a state change will trigger component rendering, but this identifier is not necessary to trigger rendering. It only needs to act as an identifier!
In this case, the features 3 and 4 of useref are used.
I use useref to initialize and give it totriggerSearchVariables, inhandleChangetaketriggerSearch.currentSet to true inhandleSelectLieutenant generaltriggerSearch.currentSet it to false, and then use it in useeffect to intercept.
Useref will not be reset with component re rendering, and its change will not trigger component re rendering.

useRef

image.png

About point 5

See the demo directly as follows:

import React, { useState,  useRef } from "react";
import ReactDOM from "react-dom";

function Example() {
  const [count, setCount] = useState(0);

  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + count);
    }, 3000);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
      <button onClick={handleAlertClick}>
        Show alert
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Example />, rootElement);

The operation results are as follows:

useRef

GIF 2021-12-22 17-13-37.gif

When I clickshow alertButton followed byClick meThe button has been clicked 3 times, and the alert is displayedcountStill 0. The reasons for this phenomenon involveevent loopConcept of:setTimeoutA new task (macro task) is formed in the event queue. Its callback function is its micro task. When I clickshow alertButtonsetTimeoutGet the initial rendering declaration incountIt will not change when the callback function is executed. Then clickClick meAfter buttoncountIs recreated, andsetTimeoutThe first one visited incountNo longer has any relationship, sosetTimeoutThe one incountIs 0.

anduseRefThe fifth feature of can be used to solve this problem.
useRefThe created object can always be retained in the component to store something (just like the this object in the class component). Even if the component is re rendered, it will not be changed.

function Example() {
  const [count, setCount] = useState(0);

  const currentCount = useRef();
  currentCount.current = count;
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + currentCount.current);
    }, 3000);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
      <button onClick={handleAlertClick}>
        Show alert
      </button>
    </div>
  );
}

useRef

GIF 2021-12-22 17-46-10.gif

In codecurrentCountThe object always exists in the component, and it remains even if the component is re rendered. thatsetTimeoutThe callback function of always gets the same one that stores the latestcountofcurrentCount

End.