# 第五週
本頁連結:https://hackmd.io/5foB4HVoT9GKTwvaJBkdKQ
## 完課獎勵說明
完整獎勵說明:https://hackmd.io/ry4GF6KWROKbx9cLf51bkA
- 2/16 前 50%:超過 100 人挑戰成功,全班直播加碼授權一年
- 前完成課程報到 -> 第四週主線
- 2/23 前 60%:框架菁英班直播 → 主題:Next.js 起步走
- 完成課程報到 -> 第六週主線 或 第五週主線 + 心得牆
- 3/9 前 80%:框架菁英班錄影(目前以 Vue 為主,React 可參考主題包含:從零建構 API、Cloud flare、前端工程師如何寫出好履歷)
- 完成課程報到 -> 第七週主線 或 第六週主線 + 心得牆
- 100%:數位完賽獎狀
## 提醒:作業繳交說明
- 所有繳交期限 3/23
- **最終延長繳交條件**:3/23 前完整繳交(沒有被直接退件),可延長批改至 4/13
- 直接退件的原因:
- 助教下載後,`npm run dev` 無法運行
- 作品不完整(作品內容有缺、有大量假字)
### 本週重點
- Hook
- 自定義 Hook
- 使用外部 Hooks:https://github.com/streamich/react-use
- React Hook Form
- React 開發優化:
- 局部 Loading
- 全畫面 Loading
- Loading State 管理
- https://www.npmjs.com/package/react-loading
- https://www.npmjs.com/package/react-spinners
- useContext → 可自行看影音課程,後續會跳 redux toolkit
## 關於 Hooks
### 1. Hook 的概念
> Hooks 實現細粒度的邏輯拆分,讓功能更小、更純粹,元件僅將需要的功能引入,或者將重複的邏輯進行封裝。
>
可以參考[課程教學](https://courses.hexschool.com/courses/react-video-course1/lectures/53655925),簡單概念如下:
1. 先撰寫一份可運作的程式碼
2. 可嘗試將相關的邏輯抽出,定義成 use… 作為獨立 hook
3. 嘗試匯入運行,確認無誤後,可建立成獨立檔案
> 剛開始,可以放到 hooks 資料夾內,並使用 use….js 命名即可
### 使用現成的 Hooks
參考:https://github.com/streamich/react-use
範例:
1. useMouse
2. *useDropArea*
3. useDebounce
## React Hook Form
### 基本表單知識
常見表單標籤
- form
- label
- input
- button
### React Hook Form
#### 基本表單觀念
1. form 、 action 、submit
2. button
3. label 與 input
#### React 常見表單問題
0. 基礎表單輸入
1. checbox 單選與複選
2. select 預設值
3. 混合(炸)
#### 為什麼要使用 React Hook Form
1. 因為原有的 React 開發表單相對困難很多:參考 - https://courses.hexschool.com/courses/react-video-course1/lectures/53655949
2. 包含錯誤回饋的部分
### 使用 React Hook Form
**基礎使用**
1. 安裝 React Hook Form:npm install react-hook-form
2. 初始化 React Hook Form
```jsx
import { useForm } from "react-hook-form"
function Component() {
const {
register, // 用來註冊表單元素
handleSubmit // 用來處理表單提交
} = useForm();
const onSubmit = (data) => { // 表單送出實際的資料內容
console.log(data);
};
return ()
}
```
1. 將表單元素套用至 input 上
```jsx=
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName")} />
<input {...register("lastName")} />
<button type="submit">送出</button>
</form>
```
- 預設值定義方式
```jsx
const {
register,
handleSubmit
} = useForm({
// 使用參數 defaultValues
defaultValues: {
firstName: "John",
lastName: "Doe"
}
})
```
- 各類表單元素套用方式
```jsx
{/* 各種表單元素,基本套用方式 */}
<input {...register("email")} />
<select {...register("category")}>
<option value="">Select...</option>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
{/* 單選 Checkbox */}
<input type="checkbox" {...register("isChecked")} /> Checkbox
{/* 多選 Checkbox */}
<label>
<input type="checkbox" {...register("like")} value="鍋燒意麵" /> Option 1
</label>
<label>
<input type="checkbox" {...register("like")} value="炒麵" /> Option 2
</label>
<label>
<input type="checkbox" {...register("like")} value="漢堡" /> Option 3
</label>
{/* 單選 Radio */}
<input type="radio" {...register('gender')} value="男" /> 男
<input type="radio" {...register('gender')} value="女" /> 女
```
**監聽當前行為**
影音課程中有兩種方法:https://courses.hexschool.com/courses/react-video-course1/lectures/53655956)
1. 取出 Watch 行為
```
import { useForm, useWatch } from "react-hook-form"
```
2. 取出 Control
```jsx
const {
register,
handleSubmit,
control, // 判斷控制的表單
} = useForm({
...
});
```
3. 將值取出,並呈現在畫面上
```jsx
const watchForm = useWatch({
control,
});
useEffect(() => {
console.log(watchForm);
}, [watchForm]);
```
**驗證方法(基礎)**
1. 驗證 required (必填,如果沒有填寫則無法送出
```jsx
<input type="text" {
...register('username', {
required: true,
})
} />
```
2. 錯誤回饋,取出 erros
```jsx
const {
register, // 用來註冊表單元素
handleSubmit, // 用來處理表單提交
control, // 判斷控制的表單
formState: { errors }, // 錯誤訊息
} = useForm({
...
});
console.log(errors); // 當有錯誤時,這裡會出現資訊
```
3. 將錯誤呈現在畫面上
```jsx
<span>錯誤訊息:{
errors.username ? '這個欄位為必填' : ''
}</span>
```
4. 可選:是否要立即做判斷
```jsx
const {
...
} = useForm({
...
mode: 'onChange', // 表單驗證的時機
});
```
**驗證方法:進階**
常見驗證技巧
參考資源:https://react-hook-form.com/docs/useform/register
```jsx
<input
type="password"
{...register("password", {
required: "密碼是必填項目",
minLength: {
value: 6,
message: "密碼長度至少需為 6 個字元",
},
maxLength: {
value: 12,
message: "密碼長度不得超過 12 個字元",
},
})}
/>
<span>
{errors.password ? errors.password.message : ""}
</span>
<br />
<input
type="email"
{...register("email", {
required: "Email 是必填項目",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "請輸入有效的 Email 格式",
},
})}
/>
<span>
{errors.email ? errors.email.message : ""}
</span>
<br />
<input type="text" {
...register('phone', {
required: '請填寫手機號碼',
pattern: {
value: /^[0-9]{10}$/,
message: '手機號碼格式錯誤',
},
})
} />
<span>錯誤訊息:{
errors.phone ? errors.phone.message : ''
}</span>
```
- 正規表達式可搭配 AI 使用 (前後補上 `/`)

### 錯誤樣式
```
className={
`${errors['email'] ? 'error-state' : ''}`
}
```
## Loading 效果開發
- 全畫面 Loading
- 可搭配:https://www.npmjs.com/package/react-spinners
- https://www.npmjs.com/package/react-loading
- 單一元素 Loading
- 可搭配:https://getbootstrap.com/docs/5.3/components/spinners/
- 列表單一元素 Loading
## 本週額外挑戰
- 預習章節閱讀:[連結](https://rpg.hexschool.com/#/training/12062543649513962870/board/content/12062543649513962883_12062543649513962890)
- 環境建置(完整看完)
- Router
- 作業連結:https://rpg.hexschool.com/#/training/12062543649513962870/board/content/12062543649513962871_12062543649513962892?tid=12062543649528478358
- 助教作業解說(週日上午 10:00)

- 團隊任務:
- https://rpg.hexschool.com/#/training/12062543649513962870/board/content/12062543649513962879_12062543649513962909