3-5 React 元件的拆分
本單元對應的專案分支為:split-components。
先前,我們在整個頁面中都只使用了一個 React 元件,並把所有的 HTML 結構包在這個元件中
在這個元件中包含所有的 HTML 結構,但是當專案一大起來之後,一個頁面中若包含所有的 HTML 結構、邏輯判斷等等,將會變得難以管理,你可以想像一隻檔案打開來後有好幾萬行,要如何找到想要修改的元素呢?
因此在 React 中,元件除了能方便開發者重複使用外,還有一點是讓開發者去管理各個「功能獨立」的元素,並且把每個元件都拆分成獨立的 JS 檔案後,管理上就會方便許多了。
在這個單元中最後呈現的畫面不會有太大的變化,但元件和檔案的拆分則會有明顯的不同。
讀者們可以先留意一下,這裡我們會先把 <div className="unit-control">...</div> 和 <div className="card-footer">...</div> 的部分先進行元件的拆分;對於中間的 <div className="converter">...</div> 區塊,因為會需要更多資料傳遞的觀念,為了避免一次吸收太多的資訊而難以消化,因此會在後面的單元再來拆分這個部分。
拆出 UnitControl 元件#
React 元件的拆分非常簡單,其實你早就會了。舉例來說,現在想要把 <div className="unit-control">...</div> 的這個區塊拆成一個獨立的元件:

只需要透過函式定義一個新的 React 元件,名稱就取為 UnitControl,要留意的是 React 元件的命名是使用大寫駝峰,因此首字需要大寫,同時因為這個元件單純只是要回傳 JSX 而沒有要做其他處理,所以可以在箭頭函式的 => 後直接回傳 JSX 即可,像這樣:
這樣就完成了一個名為 <UnitControl /> 的 React 元件,只需要在你想要使用它的地方帶入即可,像是下圖這樣:

建立 CardFooter 元件#
除了 <UnitControl /> 可以拆分成獨立的元件外,我們也進一步把 <div class="card-footer">...</div> 的部分拆成一個獨立的元件,像這是這樣:
接著同樣在原本的位置把這個元件套用進去:
💡 小提醒:這裡讀者可能會有些困惑, CardFooter 才一行而已為什麼要拆成一個元件?這主要是因為在後面的單元中將會對它做更多的變化,因此這裡實作時先把它進行拆分。
檔案拆分#
現在你會發現在同一支 app.js 中就包含了三個 React 元件,目前因為程式碼還不多,所以不會感到太過複雜,但未來如果內容變多或需要在元件中進行邏輯運算時,在一隻檔案中包含多個元件就不會是太好的做法。好在透過 ES Module 系統,可以把元件拆分成不同的檔案。
新增 components 資料夾#
現在我們先在 src 中新增 components 資料夾,並分別在裡面新增 UnitControl.js 和 CardFooter.js 這兩隻檔案,檔案目錄會長像這樣:

建立 UnitControl 檔案#
接著在 src/components/UnitControl.js 中,先匯入 React 套件,把原本寫在 App.js 中的 UnitControl 元件剪下放進來,然後用 export default 加以匯出:
caution
小提醒:只要有用到 JSX 的檔案,都記得要在最上方匯入 React 套件,檔案才能被正確解析。
建立 CardFooter#
同樣的,把原本寫在 App.js 中的 CardFooter 元件剪下放進來,然後用 export default 加以匯出:
在 App.js 中匯入 Component#
最後,回到 App.js 中,只需要把剛剛 export 的元件匯入(import)即可直接使用,程式碼幾乎不用動:
換你了:試著拆分 React 元件吧#
現在要請你試著把 UnitControl 和 CardFooter 這兩個元件拆分出來,分別放在 components 資料夾中的 UnitControl.js 和 CardFooter.js。拆分完之後,一樣記得透過 npm start 來把專案啟動起來,這時候的畫面應該一樣可以正常顯示,並且沒有任何不同:
- 在
./src/components/UnitControl.js中建立 UnitControl 元件 - 在
./src/components/CardFooter.js中建立 CardFooter 元件 - 在
./App.js中匯入 UnitControl 和 CardFooter -
npm start確認專案能正確啟動
在這個單元中,對於中間的 <div className="converter">...</div> 區塊還沒有進行元件的拆份,這是因為這個區塊有綁定事件在內,會需要更多資料傳遞的觀念,為了避免一次吸收太多的資訊而難以消化,因此會在後面的單元再來拆分這個部分。
在下一個單元中我們要先讓 CardFooter 的文字和顏色能根據網速而有不同的呈現方式。本單元相關之網頁連結、完整程式碼與程式碼變更部分可於 split-components 分支檢視:https://github.com/pjchender/learn-react-from-hooks-internet-speed-converter/tree/split-components:
