本篇將深入探討 React 19 的核心概念與實作技巧,從 Vite 專案結構開始,逐步介紹 JSX 語法、元件設計、Props 傳遞、事件處理到狀態管理。透過實際範例,你將學會如何建構可重用的元件、管理應用程式狀態,以及掌握現代 React 開發的最佳實踐。

了解專案環境

相較於 CDN 載入方式,使用 Vite 建立的 React 專案已經內建完整的開發環境。Vite 會自動處理 JSX 轉換、模組打包、熱更新等工作,讓我們專注在應用程式開發上。本章節將從 Vite 預設產生的專案結構開始,逐步了解 React 19 的核心觀念。

根元件(Root Component)

React 應用程式採用 SPA(Single Page Application,單頁應用程式) 架構,整個網站只會載入一個 index.html 檔案,所有的頁面切換和內容更新都透過 JavaScript 動態完成,不需要重新載入頁面。

在 Vite 專案中, index.html 是整個應用的入口點,它只包含一個掛載點 <div id="root"></div> 和一個 JavaScript 模組引入 <script type="module" src="/src/main.jsx"></script> 。React 會在這個掛載點渲染整個應用程式。

index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

為什麼使用 .jsx 副檔名?

.jsx 副檔名明確告訴 Vite 這個檔案包含 JSX 語法,需要進行特殊處理。雖然 Vite 也能處理 .js 檔案中的 JSX,但使用 .jsx 能讓檔案用途更清晰,也方便編輯器提供更好的語法高亮和自動補全。

main.jsx - 應用程式入口

/src/main.jsx 是整個 React 應用的入口檔案,負責初始化並渲染根元件。讓我們逐步了解每個部分的作用:

📌 核心概念說明:

  • StrictMode(嚴格模式)

  • React 19 的開發輔助工具,用於檢測潛在問題
  • 檢測不安全的生命週期、過時的 API 使用
  • 在開發模式下會 故意執行元件兩次 ,幫助發現副作用問題
  • 只在開發環境生效,生產環境會自動移除
  • createRoot(建立根節點)

  • React 18+ 引入的新 API,取代舊的 ReactDOM.render
  • 啟用 Concurrent Mode(並行模式),支援更好的效能優化
  • 語法: createRoot(DOM 元素).render(React 元件)
  • CSS 匯入

  • React 元件可以直接匯入 CSS 檔案
  • 父元件的樣式會影響所有子元件(CSS 繼承特性)
  • Vite 會自動處理 CSS 的打包和熱更新
  • 模組匯入簡化

  • Vite 支援省略 .jsx 副檔名
  • 會自動依序尋找 .js .jsx .json 檔案
  • 例: import App from './App' 會自動找到 App.jsx
  • 虛擬 DOM 渲染

  • render 方法會建立虛擬 DOM 樹
  • React 透過 Diff 演算法比較變化
  • 只更新實際改變的 DOM 部分,提升效能
  • /src/main.jsx
    import { StrictMode } from 'react'; // 引入 StrictMode 用於開發環境的嚴格檢查
    import { createRoot } from 'react-dom/client'; // React 18+ 的新 API
    import './index.css'; // 引入全域 CSS 樣式
    import App from './App'; // 引入主應用元件(省略副檔名, Vite 會自動解析出 .jsx)

    // 建立 React 根節點並渲染應用
    createRoot(document.getElementById('root')).render(
    <StrictMode>
    <App />
    </StrictMode>
    );

    React 18+ 重要變更:

    // ✅ React 18+ 正確寫法(啟用 Concurrent Mode)
    const root = createRoot(document.getElementById('root'));
    root.render(<App />);

    // ❌ React 17 舊寫法(已不推薦)
    ReactDOM.render(<App />, document.getElementById('root'));

    關鍵差異:

  • Concurrent Mode :React 18+ 預設啟用,支援自動批次更新、Suspense 等新特性
  • 更好的效能 :可中斷渲染,優先處理使用者互動
  • 未來兼容性 :React 19 的新功能都基於 createRoot API
  • JSX 轉換改進(React 17+):

    從 React 17 開始,你不再需要在每個檔案中 import React

    // ✅ React 17+ 不需要這樣宣告
    // import React, { useState, useEffect } from 'react';

    // 只需匯入使用到的 Hooks 或工具
    import { useState, useEffect } from 'react';

    function MyComponent() {
    return <div>Hello</div>; // JSX 會自動轉換,不需要 React 在作用域中
    }

    React 16 以前,因為 Babel 編譯 JSX 時會直接呼叫 React.createElement ,所以每個使用 JSX 的檔案都必須手動寫上 import React from 'react'; ,確保 React 在作用域。自 React 17 起,Babel 或 SWC 等現代編譯器會自動注入轉換函式,讓你不必再手動引入 React,JSX 可以直接使用,開發流程更簡潔。

    App.jsx - 主應用元件

    在 VSCode 中,你可以按住 Ctrl 並點擊 <App /> ,快速跳轉到 App.jsx 檔案。這是 React 應用的主要元件,所有的 UI 邏輯都從這裡開始。

    React 採用 元件樹(Component Tree) 的架構,每個元件都可以包含子元件,形成巢狀結構。在這個例子中, App main.jsx 的子元件,而 App 內部又可以包含更多子元件。每個元件都有自己獨立的邏輯、狀態和渲染輸出。

    App.jsx
    import { useState } from 'react'; // 匯入 useState Hook 用於狀態管理
    import reactLogo from './assets/react.svg'; // 匯入 React 圖片資源
    import viteLogo from '/vite.svg'; // 匯入 Vite 圖片(位於 public 目錄)
    import './App.css'; // 匯入元件專屬樣式

    function App() {
    // 宣告狀態:count 是當前值,setCount 是更新函式
    const [count, setCount] = useState(0);

    return (
    <>
    {/* Fragment 空標籤:包裹多個元素但不產生額外 DOM */}
    <div>
    <a href="https://vite.dev" target="_blank" rel="noopener noreferrer">
    <img src={viteLogo} className="logo" alt="Vite logo" />
    </a>
    <a href="https://react.dev" target="_blank" rel="noopener noreferrer">
    <img src={reactLogo} className="logo react" alt="React logo" />
    </a>
    </div>
    <h1>Vite + React</h1>
    <div className="card">
    {/* 點擊按鈕時,將 count + 1 */}
    <button onClick={() => setCount((count) => count + 1)}>
    count is {count}
    </button>
    <p>
    Edit <code>src/App.jsx</code> and save to test HMR
    </p>
    </div>
    <p className="read-the-docs">
    Click on the Vite and React logos to learn more
    </p>
    </>
    );
    }

    export default App; // 預設匯出,讓 main.jsx 可以引入

    📌 App.jsx 關鍵概念解析:

  • useState Hook(狀態管理)

    const [count, setCount] = useState(0);
    // ↑ ↑ ↑
    // 當前值 更新函式 初始值
  • count :唯讀的狀態值,用於顯示
  • setCount :更新狀態的函式,呼叫後會觸發重新渲染
  • 0 :初始值,元件第一次渲染時的狀態
  • 後續章節會詳細介紹
  • 圖片模組化 :Vite 允許直接 import 圖片,會自動處理路徑
  • CSS 匯入 :元件專屬樣式,支援 CSS Modules、PostCSS 等
  • 路徑規則
  •