React 渲染元素 (Rendering Elements)

React Element(元素)是 React 應用程式中最小的組成單位。一個 element 描述你想要在畫面上看到什麼。

const element = <h1>Hello, world</h1>

不同於瀏覽器的 DOM elements,React elements 是純粹的物件(plain objects),建立成本很低。React DOM 會負責將 React elements 更新到實際的 DOM 上。

不要把 elements 和 components 搞混了。Elements 是組成 components 的「材料」。

將 Element 渲染到 DOM

假設你的 HTML 檔案中有這樣一個 <div>

<div id="root"></div>

我們稱這個為「root」DOM 節點,因為它裡面的所有內容都會由 React DOM 來管理。

使用 React 建立的應用程式通常只會有一個 root DOM 節點。

createRoot 與 render

要將 React element 渲染到 root DOM 節點,需要使用 createRootrender

import { createRoot } from 'react-dom/client'

const root = createRoot(document.getElementById('root'))
root.render(<h1>Hello, world</h1>)

這段程式碼會在頁面上顯示 "Hello, world"。

完整的進入點範例

在典型的 React 應用程式中,進入點(通常是 main.jsxindex.jsx)會像這樣:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
import './index.css'

const root = createRoot(document.getElementById('root'))

root.render(
  <StrictMode>
    <App />
  </StrictMode>
)

程式做的事情:

  1. 使用 createRoot 取得 root DOM 節點的控制權
  2. 使用 render 方法將 React 元件渲染到該節點
  3. StrictMode 是開發輔助工具,幫助檢查潛在問題

StrictMode 嚴格模式

StrictMode 是 React 提供的開發輔助工具,它不會渲染任何可見的 UI,而是為其子元件啟動額外的檢查和警告。

import { StrictMode } from 'react'

root.render(
  <StrictMode>
    <App />
  </StrictMode>
)

StrictMode 會幫你檢查:

  • 元件是否有不安全的生命週期方法
  • 使用過時的 API
  • 意外的副作用(透過重複渲染來檢測)
StrictMode 只在開發環境中運作,在正式環境(production)中不會有任何影響,也不會降低效能。

為什麼元件會渲染兩次?

在 StrictMode 下,React 會刻意在開發環境中將元件渲染兩次,這是為了幫你發現副作用相關的問題。如果你發現某些操作被執行了兩次,這是正常的,表示 StrictMode 正在運作。

更新已渲染的 Element

React elements 是不可變的(immutable)。一旦你建立了一個 element,你就不能改變它的 children 或 attributes。

更新 UI 的唯一方式是建立一個新的 element,並再次呼叫 render

來看一個時鐘的例子:

import { createRoot } from 'react-dom/client'

const root = createRoot(document.getElementById('root'))

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  )
  root.render(element)
}

// 每秒更新一次
setInterval(tick, 1000)

這個例子每秒呼叫一次 root.render()

在實際應用中,大多數 React 應用程式只會呼叫一次 root.render()。之後的更新都是透過 state 來驅動。

React 只更新必要的部分

React DOM 會比較 element 和它的 children 與先前的狀態,只會更新必要的 DOM 來使 DOM 達到預期的狀態。

你可以使用瀏覽器的開發者工具來檢視上面時鐘的例子,會發現即使我們每秒都建立一個全新的 element 來描述整個 UI 樹,但實際上只有內容變更的文字節點會被 React DOM 更新。

這就是 React 的 Virtual DOM 機制在運作,它會計算出最小的變更,然後只更新那些需要變更的部分,大大提升了效能。