[React] useRef for preventing unnecessary re-render

When you want a component to “remember” some information, but you don’t want that information to trigger new renders, you can use a ref.

import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}

 

Note that the component doesn’t re-render with every increment. Like state, refs are retained by React between re-renders. However, setting state re-renders a component. Changing a ref does not!

 

When a piece of information is used for rendering, keep it in state. When a piece of information is only needed by event handlers and changing it doesn’t require a re-render, using a ref may be more efficient.

 

Limitations of React state don’t apply to refs. For example, state acts like a snapshot for every render and doesn’t update synchronously. But when you mutate the current value of a ref, it changes immediatel

ref.current = 5;
console.log(ref.current); // 5

This is because the ref itself is a regular JavaScript object, and so it behaves like one.

 

What advantages does this give us over just declaring and using a variable with let?

import React, {useRef} from "react";
const MyFunctionalComponent = (props) => {
    const refVariable = useRef('value');
    //versus
    let letVariable = 'value';
}
  • useRef() give you the same object ref everytime; if use variable, it creates a new variable everytime.
  • useRef() gives you something more permanent, like useState() but updating doesn't trigger re-render, very useful if you are doing a lot of manipulation in a chaining fashion, but wouldn't want to trigger a re-render until the end

 

Example:

State works like a snapshot, so you can’t read the latest state from an asynchronous operation like a timeout. However, you can keep the latest input text in a ref. A ref is mutable, so you can read the current property at any time. Since the current text is also used for rendering, in this example, you will need both a state variable (for rendering), and a ref (to read it in the timeout). You will need to update the current ref value manually.

import { useState, useRef } from 'react';

export default function Chat() {
  const [text, setText] = useState('');
  const textRef = useRef(text);

  function handleChange(e) {
    setText(e.target.value);
    textRef.current = e.target.value;
  }

  function handleSend() {
    setTimeout(() => {
      alert('Sending: ' + textRef.current);
    }, 3000);
  }

  return (
    <>
      <input
        value={text}
        onChange={handleChange}
      />
      <button
        onClick={handleSend}>
        Send
      </button>
    </>
  );
}

 

posted @ 2023-03-19 03:07  Zhentiw  阅读(24)  评论(0编辑  收藏  举报