# I ❤️ React ?

----
- #### 常用的 plugin
- #### Icon 的使用方式
- #### Validate 資料格式驗證
- #### 常用的正規化 (千分號、replace空白、數字)
- #### Environment 切換
- #### 專案討論 & QA
---
#### 打個預防針
##### 人有失蹄馬有亂足,有錯歡迎指證
---
### 常用的 plugin
- [Fontawesome](https://bit.ly/2Zlmh1w)
```shell=
npm i --save @fortawesome/fontawesome-free
```
```javascript=
import "@fortawesome/fontawesome-free/css/all.min.css";
```
```
這套可以比較方便從官網上複製icon來使用
而且只是簡單的載入css而已
```
----
- [node-sass](https://bit.ly/2LDx7rP)
```shell=
npm i node-sass --save
```
```
App.js
```
```javascript=
import "./assets/scss/site.scss"
```
```
單獨載入 Bootstrap 某功能
```
```css=
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";
@import "node_modules/bootstrap/scss/mixins";
@import "node_modules/bootstrap/scss/utilities";
```
----
- [@babel/plugin-proposal-optional-chaining](https://bit.ly/2LJ7pC2)
安裝參考(https://bit.ly/2zNuGQG)
```shell=
npm i customize-cra react-app-rewired -D
npm i @babel/plugin-proposal-optional-chaining -D
```
```javascript=
object?.key?.value
```
----
- [paginator](https://bit.ly/36dFIL3)
```shell=
npm i paginator
```
```javascript=
const paginationInfo = new paginator(
itemsCountPerPage,
howManyPageDisplayed
).build(totalRows, currentPage)
```
----
- [classnames](https://bit.ly/3cNeTzN)
```shell=
npm install classnames --save
```
```javascript=
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
```
----
- [use-form-milk](https://bit.ly/2LOvebC)
```shell=
npm install react-hook-form
```
```javascript=
const { register, handleSubmit, errors, formState } = useForm();
<form onSubmit={handleSubmit(onSubmit)}>
<input name="lastName" placeholder="Luo" ref={register} />
<input name="username" placeholder="Bill" ref={register} />
</form>
```
----
- [react-use](https://github.com/streamich/react-use)
給你滿滿的大平台

---
### icon 的使用方式
透過 command 以及多行邊編輯的方式生成 icon

---
### validate 資料格式驗證
```shell=
npm i @hapi/joi
```
```javascript=
userEmail: Joi
.string()
.email({ minDomainSegments: 2, tlds: false })
.required()
.error(errors => {
errors.forEach(err => {
switch (err.code) {
case "string.empty":
err.message = "Email can't be empty"
break
case "string.email":
err.message = "Please enter a valid email address."
break
default:
break
}
})
return errors
})
```
----
```
✅優點:
提供像是Email、日期格式等基本的format檢查
前後端都用JS開發時,可以共用Schema設定
```
```
💩缺點:
並非每種情況都可以很輕易寫成Joi Schema
有時候寫if更省時省力
```
---
### 常用的正規化
(千分號、replace空白、數字)
```javascript=
//千分號轉換
"123456".replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
//只能填數字
e.target.value.replace(/\D/g, "")
//清掉空白
" A B C D E".replace(/\s/g, "")
```
----
```
更多有的沒的
```
```C#
public const string Chinese = @"^[\u4E00-\u9FA5\uF900-\uFA2D]+$";
public const string Color = "^#[a-fA-F0-9]{6}";
public const string Date = @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$";
public const string DateTime = @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$";
public const string Email = @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$";
public const string Float = @"^(-?\d+)(\.\d+)?$";
public const string ImageFormat = @"\.(?i:jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$";
public const string Integer = @"^-?\d+$";
public const string IP = @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";
public const string Letter = "^[A-Za-z]+$";
public const string LowerLetter = "^[a-z]+$";
public const string MinusFloat = @"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$";
public const string MinusInteger = "^-[0-9]*[1-9][0-9]*$";
public const string Mobile = "^0{0,1}13[0-9]{9}$";
public const string NumbericOrLetterOrChinese = @"^[A-Za-z0-9\u4E00-\u9FA5\uF900-\uFA2D]+$";
public const string Numeric = "^[0-9]+$";
public const string NumericOrLetter = "^[A-Za-z0-9]+$";
public const string NumericOrLetterOrUnderline = @"^\w+$";
public const string PlusFloat = @"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$";
public const string PlusInteger = "^[0-9]*[1-9][0-9]*$";
public const string Telephone = @"(\d+-)?(\d{4}-?\d{7}|\d{3}-?\d{8}|^\d{7,8})(-\d+)?";
public const string UnMinusFloat = @"^\d+(\.\d+)?$";
public const string UnMinusInteger = @"\d+$";
public const string UnPlusFloat = @"^((-\d+(\.\d+)?)|(0+(\.0+)?))$";
public const string UnPlusInteger = @"^((-\d+)|(0+))$";
public const string UpperLetter = "^[A-Z]+$";
public const string Url = @"^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?$";
```
---
### Environment 切換
```
🧐我想要在執行 npm run build 的時候也可以切換不同環境變數將程式碼打包
```

----
[env-cmd](https://www.npmjs.com/package/env-cmd)
```javascript=
{
"build": "node scripts/build.js",
"build-dev": "env-cmd -f .env.development node scripts/build.js",
}
```
疑~ (https://bit.ly/3cKUV8R)
---
### 專案討論 & QA
```
NextMile
過多層的custom hook 導致Debug到懷疑人生
為了一頁只有6,7個欄位的畫面,我要開三隻程式來看狀態改到哪去了
```

😱😱😱Source Code開起來嚇嚇你先😱😱😱
----
```
個人淺見:
1.先確定好 root page 與 state 的關係後,再來考慮分離重構
```
{"metaMigratedAt":"2023-06-15T08:22:41.711Z","metaMigratedFrom":"Content","title":"I ❤️ React ?","breaks":true,"contributors":"[{\"id\":\"fddbcb39-27ff-405d-8286-3ca604c38fd2\",\"add\":6495,\"del\":400}]"}