React(MRWR)第 2 節: Creating Content with JSX
20230716Sun.
2-10. Showing Basic Content
注意!當我們的project在瀏覽器開始執行後,index.js這個檔案會是第一個被執行的!(i.e.index.js即程式的進入點)
所以我們將在index.js這個檔案中產生一些component並顯示到網頁上。大致上會有5個步驟:
step1. Import React and ReactDOM libraries
參考資料:
keywords: React、ReactDOM、Virtual DOM、diff algo
先引入React跟ReactDOM這兩個函式庫。
1 | import React from 'react'; |
可能會感到疑惑,為什麼這裡需要引入兩種函式庫?其實兩者都有各自負責的事情。
React
Library that defines what a component is and how multiple component work together.
React library負責描述特性,提供React API。類組件、函數組件、hooks、contexts、refs…這些都是React特性,而react 模塊只描述特性長什麼樣、該怎麼用,並不負責特性的具體實現。
ReactDOM
Library that knows how to get a component to show up in the browser.
負責實現特性。
react-dom、react-native 稱為渲染器,負責在不同的宿主載體上實現特性,達到與描述相對應的真實效果。比如在瀏覽器上,渲染出DOM樹、響應點擊事件等。(react-native則用於mobile之上)
step2. Get a reference to the div with ID root
我們可以從專案中的public資料夾找到index.html檔案,但會發現這個檔案中,除了一個擁有root id的空div之外,什麼都沒有了,那他又是如何顯示出東西的呢?

答案就在我們要做的第二步驟中!當我們想要顯示我們做的react appilcation時,便會去取代擁有root id的空div,或者直接渲染進擁有root id的空div裡面。
所以我們必須先抓到這個div,如此一來便能告訴react要顯示內容在這div中。
1 | const el = document.getElementById('root'); |
step3. Tell react to take control of the element
第二步驟中,我們將抓到root id的空div命名為el。接著要利用ReactDOM Library中的createRoot特性,讓我們能顯示東西在el中。
1 | const root = ReactDOM.createRoot(el); |
step4. Create a component
要記得component是一個function回傳JSX,以下範例便是創造一個名為App的component,而這個component會回傳的內容為:
Hi there!
1 | function App() { |
step5. Show the component on the screen
最後一步驟,把component渲染到螢幕上。
1 | root.render(<App />); |
2-11. What is JSX?
參考資料:
JSX是一種語法,他可以讓我們的JavaScript像是在寫HTML一樣,但是前面提過,Browser無法讀懂JSX,所以我們需要先將JSX轉譯成JS code。
複習一下第一節的內容:
而轉譯的過程便可以透過Bable來達成。(一般來說都是使用Bable)
截圖自React(MRWR)2-11課程
這裡我們可以透過Bable.io,來看JSX與經過Bable轉譯後的差異。

所以總結一下,寫下<h1>Hi there!</h1>並不能直接顯示在browser上,他只能告訴React說這裡建立了一個element,然後我們必須使用return,React才能去使用這個component。
2-12. Printing JavaScript Variables in JSX
參考資料:
接下來的章節會提到如何在JSX中使用JS的變數。
這裡將建立一個名為App的component,接著我們會在JSX中寫入JS expression(運算式),如果想要使用JS的變數,我們必須在JSX中運用curly brace(花括號/大括號)把該變數包起來,便可以呈現動態的內容了!
1 | // 4) Create a component |

但要注意的是,花括號傳入的變數不能是物件(object),否則瀏覽器會報錯。
2-13. Shorthand JS Expressions
這個章節告訴我們如何縮短JS的運算式,先以時間為例,我們現在要在螢幕上印出目前的時間,以最基本的寫法:
1 | function APP(){ |
但其實我們可以直接在大括號中填入要執行的JS運算式,不一定要先利用變數:
1 | function APP(){ |
2-16. Typical Component Layouts
接著這個章節將提到經典的component layout,也就是一般來說大多數人會如何寫一個component?
以下為常見的component寫法:

在建立component的function之中,上方主要寫一些變數或計算等等,之後要運用於JSX中的; 而下方區塊則是我們希望這個component(元件)該如何顯示在螢幕上的內容。
在這裡可以先對於component的模式有個大致概念,之後看多了,自然也會越上手、越熟悉。
2-17. Customizing Elements with Props
我們可以知道在html中如果要有一個讓使用者輸入數字的框框,可以這樣寫:
1 | <input type="number"> |
那如果現在要寫進JSX中,要怎麼寫呢?在這裡我們會運用到一個叫做props的system。
其實就跟寫html時的概念沒兩樣,我們可以從下圖知,這個範例中一共有三種property(BTW props即property的縮寫),分別為type、min、max

但這裡有個重點!就是可以跟2-12章節的概念做結合。亦即props的值,我們可以利用大括號,傳入動態的變數給props,以下為修改後的範例:
1 | function App(){ |
總結一下,在JSX中的props,props的value若是傳入變數、數字、物件或是陣列,都必須放進大括號中,而像是字串(string)則放入(雙)引號中。

尤其可以注意到物件的部份,物件的第一個大括號是給JSX的,第二個大括號則代表物件。
再來,前面2-12章節有提到「花括號傳入的變數不能是物件(object),否則瀏覽器會報錯」,但其實與此章節是有區別的:
在2-12中提到的會產生錯誤,是因為不能直接顯示出物件,但此章節我們是將物件傳入給props,把物件作為了props的值了,這樣就不會產生錯誤。
2-18. Converting HTML to JSX
2-19. Applying Styling in JSX
再來這個章節將要談,如何將HTML轉換成JSX,這裡老師給出了5個步驟:


在HTML中,屬性若為數字,我們會將數字當作字串傳入,所以用引號。但在JSX中屬性若為數字,則要以大括號傳入,雖然不這麼做程式仍然會運作,但是會從Browser中看到error。

prop的值若為boolean值會有特殊的寫法。
- 若為true,則可以直接寫prop的名字即可(但依然保持駝峰式寫法),當然如果想把true放進大括號中也是沒問題的,這裡只是提供一個更精簡的寫法。
- 若為false,則必須把false寫進大括號中

在HTML中,我們會設定一些class,而在JSX中,”class”必須改成”className”做使用。
:::danger
這裡會改為className是有原因的。因為JSX會透過Bable(之類的)轉譯成JS code,而在JS中,class為關鍵字,是有特殊語法用途的,因此在JSX裡改用”className”便是為了避免語法衝突。
:::

若我們想把CSS的樣式寫在HTML中,就是利用inline style的方式,而在JSX中,則要把inline style用物件來表達。

2-21. Extracting Components
前面我們都是把程式寫在同一個檔案中(index.js),但是當專案越來越大、越複雜時,若仍然寫在同一個檔案中,則會非常難理解整個程式。
因此,在這個章節將提到,我們會把component拆出來單獨建立一個檔案:
從上圖可知,index.js檔案將專心import以及建立root,最後將import的component給show到螢幕上。
而component的內容將丟給別的檔案來完成,例如這裡建立了一個App.js的檔案,就是要拿來專門做component用的。
而製作component的步驟大致如下:
一般來說建立來做component的檔案,檔案名稱都會以大寫作開頭!(但不一定要這麼做,只是多數人都會這麼做,類似不成紋的規定)
component必須是一個會回傳JSX的function。
1 | function App(){ |
製作好component之後,要在該檔案的底部export這個component。
1 | export default App; |
第三步驟將component export了,接著第四步驟就要在其他檔案(即會用到App component的檔案,這裡以index.js為例)中import 這個component。
1 | // index.js |
上個步驟我們在index.js中import了App這個component,接著我們便可以在index.js檔案中使用名為App的component。
1 | <App /> |
2-22. Module Systems Overview
這章節會提到export跟import。
export、import用法
首先,export有兩種方式,一種是default、一種是named。
export用default時,當我import之後,我的名稱命名不一定要跟export一樣。以下圖為例,我在App.js檔案中export了App(用default方式),但當我在index.js中要import時,發現index.js中有變數已經叫做App了!因此這裡import的名稱就改為MyApp,才不會造成名稱重複而錯誤。
- 我們可以從下圖得知,App.js檔案中,已經有export default App了,因此若我們還想再export多個變數,就需要利用named的方法做export。
- named export方法有兩種:(下圖有示範)
- 大括號
- 一條程式完成

- 而要import named export時,則需要利用大括號(如下圖)

- 另外要注意,import named export時,無法像default export一樣,import named export是無法重新命名的
import from ...
import後面from哪裡,不同來源會有不同寫法,例如說如果檔案室我們自己建立的(例如App.js),則import時會有”./“或”../“,若我們import的東西是來自package(即一開始npm 下載的各種資源),前不會有”./“或”../“。
接著可以來理解一下,”./“與”../“兩者之間的差異:
“./“用於export及import的檔案在同一個資料夾底下:
如下圖所示:
如果複雜一點,與index.js同層次的為component,所以利用”./“可以先得到component,之後在進入到下一層次,也就是我們需要的App.js(如下圖所示)
而”../“則是返回到前一層(可以理解”./“是同一層),所以以下方為例:
