Udemy課程:Modern React with Redux [2023 Update]

20230716Sun.

2-10. Showing Basic Content

注意!當我們的project在瀏覽器開始執行後,index.js這個檔案會是第一個被執行的!(i.e.index.js即程式的進入點)

所以我們將在index.js這個檔案中產生一些component並顯示到網頁上。大致上會有5個步驟:

step1. Import React and ReactDOM libraries

參考資料:

  1. [筆記] Why React?
  2. Virtual DOM | 為了瞭解原理,那就來實作一個簡易 Virtual DOM 吧!
  3. 從react和react-dom的關係開始
  4. diff 算法深入一下?

keywords: React、ReactDOM、Virtual DOM、diff algo
先引入React跟ReactDOM這兩個函式庫。

1
2
import React from 'react';
import ReactDOM from 'react-dom/client';

可能會感到疑惑,為什麼這裡需要引入兩種函式庫?其實兩者都有各自負責的事情。

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
2
3
function App() {
return <h1>Hi there!</h1>;
}

step5. Show the component on the screen

最後一步驟,把component渲染到螢幕上。

1
root.render(<App />);

2-11. What is JSX?

參考資料:

  1. How to render Jsx code in the browser
  2. 讓瀏覽器看懂 JSX 的新選擇 HTM

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

參考資料:

  1. Writing Markup with JSX
  2. JavaScript in JSX with Curly Brace

接下來的章節會提到如何在JSX中使用JS的變數。

這裡將建立一個名為App的component,接著我們會在JSX中寫入JS expression(運算式),如果想要使用JS的變數,我們必須在JSX中運用curly brace(花括號/大括號)把該變數包起來,便可以呈現動態的內容了!

1
2
3
4
5
6
7
8
9
10
// 4) Create a component

function App() {
let message = "Bye there!";
if (Math.random() > 0.5){
message = "Hi there!";
}

return <h1>{message}</h1>;
}

但要注意的是,花括號傳入的變數不能是物件(object),否則瀏覽器會報錯。


2-13. Shorthand JS Expressions

這個章節告訴我們如何縮短JS的運算式,先以時間為例,我們現在要在螢幕上印出目前的時間,以最基本的寫法:

1
2
3
4
5
6
function APP(){
const date = new Date();
const time = date.toLocaleTimeString();

return <h1>{time}</h1>;
}

但其實我們可以直接在大括號中填入要執行的JS運算式,不一定要先利用變數:

1
2
3
function APP(){
return <h1>{new Date().toLocaleTimeString()}</h1>
}

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
2
3
4
5
6
7
8
9
10
11
function App(){
const inputType = "number";
const minValue = 5;

return (
<input
type = {inputType}
min = {minValue}
/>
)
}

總結一下,在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個步驟:

Step 1.
將prop 利用駝峰式命名

Step 2.
屬性若為數字則必須使用大括號(curly braces { })

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

Step 3.
prop的值若為boolean值(true or false)

prop的值若為boolean值會有特殊的寫法。

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

Step 4.
class改寫為className

在HTML中,我們會設定一些class,而在JSX中,”class”必須改成”className”做使用。

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

Step 5.
inline style在JSX中用物件來表示

若我們想把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的步驟大致如下:

Step 1.
建立一個檔案

一般來說建立來做component的檔案,檔案名稱都會以大寫作開頭!(但不一定要這麼做,只是多數人都會這麼做,類似不成紋的規定)

Step 2.
製作component

component必須是一個會回傳JSX的function。

1
2
3
function App(){
retern <h1>...</h1>
}
Step 3.
export the component

製作好component之後,要在該檔案的底部export這個component。

1
export default App;
Step 4.
import the component

第三步驟將component export了,接著第四步驟就要在其他檔案(即會用到App component的檔案,這裡以index.js為例)中import 這個component。

1
2
// index.js
import App from "./App.js";
Step 5.
使用component

上個步驟我們在index.js中import了App這個component,接著我們便可以在index.js檔案中使用名為App的component。

1
<App />

2-22. Module Systems Overview

這章節會提到export跟import。

export、import用法

首先,export有兩種方式,一種是default、一種是named。

第一種
default用法

export用default時,當我import之後,我的名稱命名不一定要跟export一樣。以下圖為例,我在App.js檔案中export了App(用default方式),但當我在index.js中要import時,發現index.js中有變數已經叫做App了!因此這裡import的名稱就改為MyApp,才不會造成名稱重複而錯誤。

第二種
named用法
  1. 我們可以從下圖得知,App.js檔案中,已經有export default App了,因此若我們還想再export多個變數,就需要利用named的方法做export。
  2. named export方法有兩種:(下圖有示範)
    • 大括號
    • 一條程式完成
  3. 而要import named export時,則需要利用大括號(如下圖)
  4. 另外要注意,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(如下圖所示)

而”../“則是返回到前一層(可以理解”./“是同一層),所以以下方為例: