iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

你 React 了嗎? 30 天解鎖 React 技能系列 第 20

[DAY 20] useRef 儲存資料與指定 DOM 元素

  • 分享至 

  • xImage
  •  

cover

認識 useRef

在寫原生 JavaScript 時,我們常常會用 document.querySelector 來獲取 DOM 元素,在 React 你可以使用 useRef 直接在元素上做綁定,已達到指定 DOM 的行為動作。除了訪問 DOM,useRef 還可以用來儲存資料、抓取以前的值。

useRef 會自己建立一個 mutable ref object,裡面會有一個 current 屬性設為相應的 DOM 節點或資料,不會隨著元件 re-render 被重新創造,所以 useRef 每次都會返回同一個 ref object

Mutable object:以傳址(by reference)方式被儲存,物件被創造後,參考固定,但參考的記憶體內容可以改變,如 JavaScript 的參考型別 Object、Array、Function 等

Immutable object:以傳值(by value)方式被儲存,物件被創造後,其 value 無法被改變,如 JavaScript 的原始型別 number、string、null、undefined、boolean 等


useRef 使用方法

  • 從 react 中載入 useRef
  • 設定 useRef 初始值
  • 抓取 useRef 的值

1. 從 react 中載入 useRef

import { useRef } from "react";

2. 設定 useRef 初始值

const refContainer = useRef(initialValue);

refContainer 為自定義變數

initialValue 為初始值,可以為任何值

3. 抓取 useRef 的值

refContainer.current

.current 取得 ref object 的值,實際操作會在使用情境做說明


useRef 使用情境

  • 指定 DOM 元素做操作
  • 計算渲染次數
  • 儲存不會導致畫面渲染的資料 (如抓取以前的值)

1. 指定 DOM 元素做操作

import { useEffect, useRef } from "react";

const App = () => {
  const myInput = useRef();

  useEffect(() => {
    myInput.current.focus();
  }, []);

  return (
    <div>
      <label>Name:</label>
      <input type="text" ref={myInput} />
    </div>
  );
};

export default App;

情境說明:

  • 指定 input 在一開始渲染後游標會自動跑到輸入欄位

useRef

操作說明:

  • 在指定的 input 加上 ref 屬性,自訂變數名稱
  • 創建 useRef 指向自訂變數名稱
  • 從 .current 獲取 dom元素 <input type="text" />,並在 useEffect 操作 .focus 動作

更新 useRef 是 side Effect 的行為,因此要在 useEffect 或 event handler 裡執行

打開 codesandbox 程式碼範例 看看吧!


2. 計算渲染次數

import { useRef, useEffect, useState } from "react";

const App = () => {
  const [name, setName] = useState("");

  const renderCount = useRef(1);

  useEffect(() => {
    renderCount.current += 1;
  });

  return (
    <>
      <input
        type="text"
        value={name}
        onChange={(e) => {
          setName(e.target.value);
        }}
      />
      <p>I rendered {renderCount.current} times!</p>;
    </>
  );
};

export default App;

情境說明:

  • 在輸入框輸入文字,useRef 會計算每次渲染的次數

useRef

操作說明:

  • 設定一個綁定 useState 的輸入框
  • 創建 useRef,初始值為 1
  • useEffect 沒有 dependencies,所以每次 re-render 時都會執行 renderCount.current += 1

打開 codesandbox 程式碼範例 看看吧!


3. 儲存不會導致畫面渲染的資料

import { useState, useRef, useEffect } from "react";

const App = () => {
  const [name, setName] = useState("");
  const previousName = useRef(name);

  useEffect(() => {
    previousName.current = name;
    console.log(previousName.current);
  }, [name]);

  return (
    <div>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />

      <p>
        My name is <span>{name}</span>
      </p>

      <p>
        My previous name is
        <span>{previousName.current}</span>
      </p>
    </div>
  );
};

export default App;

情境說明:

  • 輸入框輸入文字後,會顯示出輸入後、上一次輸入的文字

useRef

操作說明:

  • 設定一個綁定 useState 的輸入框
  • 創建 useRef,初始值為 name,也就是空字串
  • 所以每次更新 name 時都會執行 previousName.current = name

ref 與 state 的差異就是 ref 更新不會觸發 re-render,state 才會,所以即使 ref 已更新成輸入後的 name,畫面也不會隨著渲染,會在下一次 useState re-render 後出現

打開 condsandbox 程式碼範例 看看吧!


結語

之前比較常看到 useRef 用來操作 dom,原來也可以定義不會導致畫面重新渲染的資料,理解了 ref 跟 state 的使用上是差在 ref 不會觸發 re-render,今天到這邊結束,明天再繼續吧!!


Reference

Learn useRef in 11 Minutes
一個範例讓你搞懂useState, useRef, useEffect | 5分鐘快速教學


本文將同步更新至我的部落格
Lala 的前端大補帖



上一篇
[DAY 19] useCallback 函式記憶體
下一篇
[DAY 21] Custom Hook - 客製你自己的 Hook
系列文
你 React 了嗎? 30 天解鎖 React 技能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言