iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0
Modern Web

雙向奔赴的websocket與冰冷的react系列 第 13

[day13]React基礎教學(3)useRef

  • 分享至 

  • xImage
  •  

useRef獲取Dom元素

useRef是React中的一個 Hook使用Hook要記得import React, { useRef } from 'react'之前好像忘記說了
主要有以下幾個功能:

  • 存取 DOM 元素:useRef 可以用來存取 React 組件渲染的 DOM 元素,類似於原生 JavaScript 中的 document.getElementById() 或 querySelector()。通過 ref 屬性將 useRef 綁定到某個 DOM 元素,從而在組件中訪問該元素。
  • 持久化數據:useRef 提供了一個可變的 .current 屬性,可以在不同的渲染之間保留其值,而不會因為重新渲染而丟失。這使得它適合保存一些不需要觸發重新渲染的數據。
  • 不會觸發重新渲染:與 useState 不同,useRef 的值改變時,並不會觸發組件的重新渲染。這意味著你可以用它來追蹤某些狀態而不需要重新渲染組件。

範例

  const inputRef = useRef(null)
  const showDom = () => {
    console.dir(inputRef.current)
  //inputRef.current.value='123'
  }
  return(
      <>
        <div>
            <input type="text" ref={inputRef} />
            <button onClick={showDom}>show dom</button>
        </div>
      </>
  )

為何要設置為null呢?

  • 初始值為 null:當組件首次渲染時,useRef 還沒有指向任何 DOM 元素,因此你通常將 ref 初始化為 null,這表示還沒有對應的 DOM 元素。在組件完成渲染並且 DOM 結構生成之後,useRef 才會指向對應的 DOM 元素。
  • React 在渲染完成後設置 ref:在組件渲染後,React 會自動將 inputRef.current 設置為對應的 DOM 節點,這時 useRef(null) 中的 null 會被 DOM 節點覆蓋掉。所以,useRef(null) 中的 null 只是為了在渲染之前有一個安全的初始值,防止出現未定義的錯誤。

而相較原生的js寫法useRef更適合 React:因為 useRef 是與 React 的生命週期協同工作,它會自動更新引用。

如果用document.getElementById()

import React, { useState, useRef } from 'react';

function Practise() {
  const [showInput, setShowInput] = useState(true);
  const inputRef = useRef(null);

  const toggleInput = () => {
    setShowInput(!showInput); // 控制 input 的顯示與隱藏
  };

  const focusInput = () => {
    if (inputRef.current) {
      inputRef.current.focus(); // 使用 useRef 訪問 DOM 元素
      console.log(jsinput)
    } else {
      console.log('Input is not available');
    }
  };

  const jsinput = document.getElementById('inp')

  return (
    <div>
      <button onClick={toggleInput}>
        {showInput ? 'Hide Input' : 'Show Input'}
      </button>
      {showInput && <input ref={inputRef} id="inp" type="text" />}
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}

export default Practise;

以上就會遇到一個問題:如果該元素是條件渲染的(如 showInput 控制的 input 元素),則在初次渲染時,該元素還不存在。因此,當你使用 document.getElementById('btn') 來捕捉 input 元素時,這段代碼會在首次渲染時執行,但此時 DOM 中尚未有 id="btn" 的 input 元素,因此會返回 null。

總結

  • 在靜態或固定的畫面下,使用 document.getElementById() 來捕捉 DOM 元素可能不會有問題。然而,在 React 中使用 getElementById() 存在風險,特別是在條件渲染或頻繁重新渲染的情況下,因為 DOM 可能會被移除或重建。

  • useRef 更適合 React 的設計理念:useRef 是與 React 的生命週期和虛擬 DOM 緊密結合的,當 DOM 結構發生變化時,它會自動更新引用,保持引用最新的 DOM 元素。

  • 避免打破 React 的單向數據流結構:React 強調單向數據流和聲明式編程。如果你頻繁使用 getElementById() 來直接操作 DOM,可能會打破 React 的數據流結構,導致應用行為變得不可預測。使用 useRef,則可以確保 React 對 DOM 操作的完整控制,同時避免這些潛在問題。

最近有點忙QAQ,今天先這樣


上一篇
[day12]React基礎教學(2)事件綁定\useState
下一篇
[day14]React基礎教學(4)useEffect
系列文
雙向奔赴的websocket與冰冷的react30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言