Vibe Coder

React 入門:把 UI 變成可組裝的元件

React 用元件描述畫面,資料變了就自動重新渲染,不用手動操作 DOM。理解元件、Props(父傳子的資料)和 State(元件自己的記憶)這三個概念,就理解了 React 的八成,你的目標是讀懂並指揮 AI 修改,不需要從零精通。
React 入門:把 UI 變成可組裝的元件

React 入門:把 UI 變成可組裝的元件

Next.js、Vite 加 React 是 AI 最常生成的前端框架,不懂 React 就看不懂 AI 生的程式碼,更別說指揮它修改。

好消息是你不需要精通 React,只需要理解元件、Props、State 這三個核心概念,就掌握了它八成的邏輯,其他都是細節。

你將學到什麼

為什麼都用 React

資料變了畫面自動更新,不用手動操作 DOM。

元件:UI 的積木

一個回傳畫面的函式,組合起來就是完整頁面。

Props 和 State

父元件傳進來的資料,跟元件自己的記憶,差在哪裡。

useEffect 呼叫 API

元件載入時自動取得資料的標準寫法。

為什麼現在的前端都用 React

傳統 HTML 加 JS 的做法,資料變了要手動更新 DOM,容易出錯。React 的解法是描述「什麼資料對應什麼畫面」,資料變了 React 自動更新 DOM。

傳統做法React 做法
手動用 querySelector 加 textContent 更新State 改變,畫面自動重新渲染
邏輯散落在各個事件監聽裡邏輯封裝在元件裡,容易測試和複用
大型應用難以維護元件化讓大型應用可以拆解管理

元件:把 UI 拆成積木

React 的元件就是一個回傳 JSX 的函式。JSX 看起來像 HTML,但其實是 JavaScript。

// 元件名稱大寫開頭
function WeatherCard() {
  return (
    <div className="card">
      <h2>台北</h2>
      <p>28°C,晴天</p>
    </div>
  )
}

// 使用元件,像 HTML 標籤一樣
function App() {
  return (
    <div>
      <WeatherCard /> {/* 自閉合,因為沒有子元素 */}
    </div>
  )
}

Props:元件的輸入

Props 是從父元件傳給子元件的資料,讓同一個元件可以顯示不同內容。

// 子元件:接收 props
function WeatherCard({ city, temperature, description }) {
  return (
    <div className="card">
      <h2>{city}</h2>
      <p>{temperature}°C,{description}</p>
    </div>
  )
}

// 父元件:傳入 props
function App() {
  return (
    <div>
      <WeatherCard city="台北" temperature={28} description="晴天" />
      <WeatherCard city="東京" temperature={22} description="多雲" />
    </div>
  )
}

State:元件的記憶

import { useState } from 'react'

function SearchBar() {
  // [目前值,更新函式] = useState(初始值)
  const [city, setCity] = useState('')
  const [weather, setWeather] = useState(null)

  const handleSearch = async () => {
    const data = await fetchWeather(city)
    setWeather(data) // State 更新,元件重新渲染
  }

  return (
    <div>
      <input value={city} onChange={e => setCity(e.target.value)} />
      <button onClick={handleSearch}>查詢</button>
      {weather && <p>{weather.temp}°C</p>}
    </div>
  )
}
Props(唯讀資料)state 改變元件重新渲染App(父元件)WeatherCard(子元件)useState元件內部記憶
Props 由父元件往下傳,State 是元件自己的記憶。

useEffect:副作用和 API 呼叫

import { useState, useEffect } from 'react'

function WeatherApp() {
  const [data, setData] = useState(null)

  // 空陣列表示只在元件第一次載入時執行一次
  useEffect(() => {
    fetchWeather('Taipei').then(d => setData(d))
  }, [])

  return <p>{data ? data.temp : '載入中…'}</p>
}
useEffect 最常見的錯誤忘記加空陣列會導致無限迴圈(每次渲染都呼叫一次 API),或依賴陣列忘記加值導致用到舊的資料。遇到奇怪的行為,先檢查 useEffect 的依賴陣列。

練習:讀懂一個計數器元件

function Counter({ initialCount = 0, step = 1 }) {
  const [count, setCount] = useState(initialCount)
  return (
    <div>
      <p>目前:{count}</p>
      <button onClick={() => setCount(count + step)}>+{step}</button>
    </div>
  )
}
試著自己說一次Props 是 initialCount(初始數字,預設零)和 step(每次加多少,預設一)。State 是 count(目前計數,初始值來自 initialCount)。渲染邏輯:顯示目前 count,點擊按鈕讓 count 增加 step,按鈕文字也會隨 step 改變。

下一步的練習:把靜態的天氣卡片改成有輸入框的互動元件,點擊查詢後用 useEffect 呼叫真實的天氣 API,更新 State 讓卡片顯示真實的溫度,並加入載入中和錯誤狀態的處理。

延伸學習

把這篇文章分享給需要的人FacebookLINEThreadsX

常見問答

Props 和 State 有什麼不同?
Props 是父元件傳給子元件的資料,是唯讀的,元件自己不能修改;State 是元件自己管理的可變資料,用 useState 定義,State 改變時元件會重新渲染。
為什麼 useEffect 常常無限迴圈?
最常見的原因是忘記加空陣列作為第二個參數,導致每次重新渲染都再呼叫一次 API,形成無限迴圈。空陣列表示這個副作用只在元件第一次載入時執行一次。
JSX 跟 HTML 有什麼差異?
JSX 幾乎和 HTML 一樣,但 class 要寫成 className、for 要寫成 htmlFor,所有標籤都要關閉包含自閉合標籤,JS 表達式要用大括號包起來。
什麼是 Hook?
Hook 是 React 提供的特殊函式,名稱以 use 開頭,例如 useState、useEffect,只能在 function component 的頂層呼叫,不能寫在條件式或迴圈裡面。