# 第二週: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 } ] ```