你的第一個 Component

Component 是 React 的核心概念之一,它們是建構使用者介面 (UI) 的基礎,是你踏上 React 旅程的完美開端!

You will learn

  • 什麼是 Component
  • Component 在 React 中扮演了什麼角色
  • 如何編寫你的第一個 React Component

Components: UI 的建構塊

在網頁中,HTML 允許我們透過使用內建標籤來創建富有結構的文件,像是 <h1><li>

<article>
<h1>My First Component</h1>
<ol>
<li>Components: UI Building Blocks</li>
<li>Defining a Component</li>
<li>Using a Component</li>
</ol>
</article>

此 markup 以 <article> 來表示文章,以 <h1> 來表示它的標題, 並且使用 <ol> 來表示有序的(縮寫)列表內容,這些 markup 結合了 CSS 樣式,以及使用 JavaScript 展現互動性,每一個側邊欄、頭像、互動視窗的背後都是這麼運作的-你在網頁上所看到的每一個 UI 模組。

React 允許你將 markup、CSS 以及 JavaScript 結合為自定義「component」, 即應用程式中可複用的 UI 元素。上文中的程式碼可以改寫為一個能夠 render 在各個頁面上的 <TableOfContents /> component,實際上,使用的依舊是 <article><h1> 等相同的標籤。

就像是 HTML 標籤一樣,你可以編寫、排序以及使用巢狀結構來設計整個頁面。例如,你正在看閱讀的文件頁面就是由 React component 所組成:

<PageLayout>
<NavigationHeader>
<SearchBar />
<Link to="/docs">Docs</Link>
</NavigationHeader>
<Sidebar />
<PageContent>
<TableOfContents />
<DocumentationText />
</PageContent>
</PageLayout>

隨著專案的成長,你會發現有許多設計可以透過複用已經完成的 component 來實現,進而加速你的開發時程。上文所提到的列表內容,可以透過 <TableOfContents /> component 添加到任意頁面中!你甚至可以使用 React 開源社群(例如 Chakra UIMaterial UI)所分享的大量 component 來快速啟動開發。

定義 component

傳統網頁開發時,網頁開發者會使用標記式語言來描述內容,然後透過 JavaScript 來實現互動,這種方式展現了良好的網頁互動。現今許多的網頁與應用程式都需具有互動性。React 將互動性視為重要指標,並且使用了相同的技術:React component 是一個可以使用 markup 進行擴展的 JavaScript 函式,如下所示(你可以編輯下方的範例):

export default function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3Am.jpg"
      alt="Katherine Johnson"
    />
  )
}

以下為建構 component 的方法:

第一步:Export the component

export default 前綴是一種 JavaScript 標準語法 (並非 React 特性)。它允許你標記檔案中的主要函式,以便你之後可以在其他檔案 import 它。(更多 import 內容請參閱 Importing 和 Exporting Component !)

第二步:定義函式

透過 function Profile() { } 定義名為 Profile 的 JavaScript 函式。

Pitfall

React component 為常規的 JavaScript 函式,但它們的名稱必須以大寫字母為開頭,否則將無法運行!

第三步:添加 markup

component 會回傳一個帶有 srcalt 屬性的 <img /> 標籤。<img /> 寫法像 HTML,但它實際上是 JavaScript!這種語法被稱為 JSX,它允許你在 JavaScript 中嵌入 markup。

回傳的內容可以全寫在同一行,如下方 component:

return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />;

但是,如果你的 markup 與 return 關鍵字不在同一行,則必須使將它們包裹在一對括號中,如下所示:

return (
<div>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</div>
);

Pitfall

沒有使用括號包裹的話,任何在 return 下一行的程式碼都 將被忽略

使用 component

現在,你已經定義了 Profile component,你可以將它們嵌套進其他的 component 中。舉例來說,你可以 export 一個包含多個 Profile component 的 Gallery component:

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

瀏覽器看見了什麼

注意下方兩者的區別:

  • <section> 是小寫的,所以 React 知道我們指的是 HTML 標籤。
  • <Profile /> 的開頭為大寫字母 P,所以 React 知道我們想要使用的是名為 Profile 的 component。

Profile 包含了更多 HTML:<img />。瀏覽器最後看見的內容會是這樣:

<section>
<h1>Amazing scientists</h1>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</section>

嵌套與組織 component

Component 為常規的 JavaScript 函式,所以你可以將多個 component 放在同一個檔案中。這在 component 相對較小或是彼此關係緊密時是非常方便的。如果檔案變得過於擁擠,你可以隨時將 Profile 移至不同的檔案。你可以立即在 import 相關章節 學習如何做到這些。

由於 Profile component 在 Gallery 中被 render-甚至數次!-我們可以將 Gallery 稱為 parent component,將每個 Profile 視為「child」render。這是 React 神奇所在之一,你可以透過定義 component 一次,然後根據需求在多個地方多次使用。

Pitfall

Component 可以 render 其他的 component,但是請不要嵌套它們的定義:

export default function Gallery() {
// 🔴 Never define a component inside another component!
function Profile() {
// ...
}
// ...
}

上方這段程式碼非常慢,並且將導致 bug 的發生。因此,你應該在頂層定義每個 component:

export default function Gallery() {
// ...
}

// ✅ Declare components at the top level
function Profile() {
// ...
}

當 child component 需要獲取 parent 的數據,你需要 透過 props 傳遞,而不是嵌套定義。

Deep Dive

萬物皆是 component

你的 React 應用程式從「root」component 開始。通常,在你啟動一個新專案時,它會自動被創建。例如,如果你使用 CodeSandboxNext.js 框架,root component 會定義在 pages/index.js 中。在這些例子中,你一直在 export root component。

大多數 React 應用程式只有 component。這意味著你不僅可以將 component 用於具有複用性的部分,例如按鈕,還可以用於更大規模的地方,像是側邊欄、列表以及完成最終的完整頁面!Component 是組織 UI 程式碼與 markup 的一種便捷方式,即便部分的 component 只使用了一次。

基於 React 的框架 更進一步。它們不只是使用空的 HTML 檔案並讓 React 通過 JavaScript 管理頁面,它們還會自動從你的 React component 中生成 HTML。這使得你的應用程式在 JavaScript 程式碼載入之前就能顯示一些內容。

儘管如此,許多網站僅使用 React 來增添「互動性」,它們有許多 root component,而不是整個頁面中的單個 component。你可以根據需求盡可能多或盡可能少地使用 React。

Recap

你剛剛第一次體驗了 React!讓我們來回顧一些重點。

  • React 允許你創建 component,應用程式中可複用的 UI 元素

  • 在 React 應用程式中,所有的 UI 模塊都是一個 component。

  • React component 是常規的 JavaScript 函式,除了:

    1. 它們的名字總是以大寫字母為開頭。
    2. 它們回傳 JSX markup。

Challenge 1 of 4:
Export the component

由於 root component 沒有被 export,導致這個沙箱無法運作:

function Profile() {
  return (
    <img
      src="https://i.imgur.com/lICfvbD.jpg"
      alt="Aklilu Lemma"
    />
  );
}

請試著在查閱解答前自行修復它!