# 第二週:React 開發環境與元件
- 請務必提醒講師 “錄影”
- 課程最終目標,完成 TodoList
- 基礎難度:約 2 ~ 3 週課程即可完成
- 進階難度:約 4 週課程可以完成
- 作品參考:https://works.hexschool.io/#/
### 做作業正確的「心態」
- 試著自己寫,~~用一個番茄鐘解決它~~
- 試著五分鐘後,還是不會寫,就去翻解答、翻別人的
- 照著打也沒關係,但請把註解都打出來
- 如果還有餘力,請重新撰寫一次
## 第二週課綱核心:
- 複習 useState 與介紹 useEffect
- 元件化:
- 什麼是元件
- 元件特性:狀態獨立
- 元件狀態傳遞、元件方法傳遞
- 什麼時候要建立元件
- 元件生命週期(useState 與 useEffect 運作原理)
## useState 與 useEffect
- useState 複習
- 為什麼要用到 useEffect 與 useEffect 介紹
**複習情境:**
> 範例:AboutUseState (訂單 CRUD)
>
- 原始的資料列表,包含名稱、金額、id
- 為這筆資料表,新增新的資料
- 刪除資料中的其中一筆
- 當所有資料變動後,將資料金額進行總和
### useEffect - 當狀態改變時,重新執行特定的函式
> 範例:WhyUseEffect
>
1. 為什麼使用 useEffect
1. useState 的運作概念:當 useState 觸發時,全元件的資料都會更新一次
2. **使用情境:**
1. 第一次運行時
2. 監聽特定值
## 元件
### 1. 元件示範
將以下畫面轉成元件
https://getbootstrap.com/docs/5.3/examples/album/
> 新手那麼怕元件,該怎麼辦?
那就不要急著面對它
>
### 2. 元件狀態、方法管理
> 延伸閱讀:React 中的 `is missing in props validation` 參考[解決方案](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prop-types.md)*。
如果是新手,會建議先略過*
>
**Props:**
- 傳入值的方法
- Props:前內後外
**轉換秘訣 → 「秘傳」**
1. **先解決版型問題**:複製片段 JSX 程式碼,並建立新檔案儲存
2. **匯入版型元件**:import 該元件,並替換該區塊
3. **最後解決邏輯**:如果該狀態、方法外層也用不到,可以放到內層元件;反之,其餘使用 Props 的方式由外向內傳入
### 3. 什麼時候建立元件
**大原則**
- 程式碼太長的時候
- 當區塊可以重複利用時
- 邏輯特殊,與當前元件差異過大時
## 作業
餐點管理工具
- Level 1:**直接參考解答**,至少製作三個元件(可選擇:左側餐點列表單一品項、單一 <tr>、下方的訂單摘要),要會動
- Level 2:**參考解答**製作菜單工具,可加入購物車並產出結果
- 挑戰中**省略:刪除、調整數量的功能**
- 一樣需要至少製作三個元件
- Level 3(挑戰):**不參考解答**製作菜單工具,可加入購物車並產出結果
- 不省略任何功能
- 重複品項無法重複加入,僅會增加數量 1
- 至少製作三個元件
- 客製化版型
解答連結:
- 執行範例:https://www.casper.tw/react-2023-homework/#/week2
- 原始碼:https://github.com/Wcc723/react-2023-homework/blob/main/src/pages/Week2.jsx
- 作業繳交連結:https://rpg.hexschool.com/training/37/show?embedhm=CqlyVMtBQhuN5dCYWNcBCA
作業使用者故事:
1. 點餐人員可以將左側的品項加入購物車
2. 點餐人員,可以刪除、調整購物車品項數量(Level 2 可不做)
3. 點餐人員可加入備註
4. 點餐人員可以建立訂單
```html
<div id="root">
<div class="container mt-5">
<div class="row">
<div class="col-md-4">
<div class="list-group">
<a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">珍珠奶茶</h5>
<small>$50</small>
</div>
<p class="mb-1">香濃奶茶搭配QQ珍珠</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">冬瓜檸檬</h5>
<small>$45</small>
</div>
<p class="mb-1">清新冬瓜配上新鮮檸檬</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">翡翠檸檬</h5>
<small>$55</small>
</div>
<p class="mb-1">綠茶與檸檬的完美結合</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">四季春茶</h5>
<small>$45</small>
</div>
<p class="mb-1">香醇四季春茶,回甘無比</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">阿薩姆奶茶</h5>
<small>$50</small>
</div>
<p class="mb-1">阿薩姆紅茶搭配香醇鮮奶</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">檸檬冰茶</h5>
<small>$45</small>
</div>
<p class="mb-1">檸檬與冰茶的清新組合</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">芒果綠茶</h5>
<small>$55</small>
</div>
<p class="mb-1">芒果與綠茶的獨特風味</p></a
><a href="#" class="list-group-item list-group-item-action"
><div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">抹茶拿鐵</h5>
<small>$60</small>
</div>
<p class="mb-1">抹茶與鮮奶的絕配</p></a
>
</div>
</div>
<div class="col-md-8">
<table class="table">
<thead>
<tr>
<th scope="col" width="50">操作</th>
<th scope="col">品項</th>
<th scope="col">描述</th>
<th scope="col" width="90">數量</th>
<th scope="col">單價</th>
<th scope="col">小計</th>
</tr>
</thead>
<tbody>
<tr>
<td><button type="button" class="btn btn-sm">x</button></td>
<td>四季春茶</td>
<td><small>香醇四季春茶,回甘無比</small></td>
<td>
<select class="form-select">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
</td>
<td>45</td>
<td>45</td>
</tr>
<tr>
<td><button type="button" class="btn btn-sm">x</button></td>
<td>翡翠檸檬</td>
<td><small>綠茶與檸檬的完美結合</small></td>
<td>
<select class="form-select">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
</td>
<td>55</td>
<td>55</td>
</tr>
</tbody>
</table>
<div class="text-end mb-3">
<h5>總計: <span>$100</span></h5>
</div>
<textarea
class="form-control mb-3"
rows="3"
placeholder="備註"
></textarea>
<div class="text-end">
<button class="btn btn-primary">送出</button>
</div>
</div>
</div>
<hr />
<div class="row justify-content-center">
<div class="col-8">
<div class="card">
<div class="card-body">
<div class="card-title">
<h5>訂單</h5>
<table class="table">
<thead>
<tr>
<th scope="col">品項</th>
<th scope="col">數量</th>
<th scope="col">小計</th>
</tr>
</thead>
<tbody>
<tr>
<td>翡翠檸檬</td>
<td>7</td>
<td>385</td>
</tr>
<tr>
<td>冬瓜檸檬</td>
<td>7</td>
<td>315</td>
</tr>
<tr>
<td>冬瓜檸檬</td>
<td>4</td>
<td>180</td>
</tr>
</tbody>
</table>
<div class="text-end">備註: <span>都不要香菜</span></div>
<div class="text-end">
<h5>總計: <span>$145</span></h5>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
```
資料:
```html
const data = [
{
"id": 1,
"name": "珍珠奶茶",
"description": "香濃奶茶搭配QQ珍珠",
"price": 50
},
{
"id": 2,
"name": "冬瓜檸檬",
"description": "清新冬瓜配上新鮮檸檬",
"price": 45
},
{
"id": 3,
"name": "翡翠檸檬",
"description": "綠茶與檸檬的完美結合",
"price": 55
},
{
"id": 4,
"name": "四季春茶",
"description": "香醇四季春茶,回甘無比",
"price": 45
},
{
"id": 5,
"name": "阿薩姆奶茶",
"description": "阿薩姆紅茶搭配香醇鮮奶",
"price": 50
},
{
"id": 6,
"name": "檸檬冰茶",
"description": "檸檬與冰茶的清新組合",
"price": 45
},
{
"id": 7,
"name": "芒果綠茶",
"description": "芒果與綠茶的獨特風味",
"price": 55
},
{
"id": 8,
"name": "抹茶拿鐵",
"description": "抹茶與鮮奶的絕配",
"price": 60
}
]
```