# I ❤️ React ? ![](https://i.imgur.com/2O3WOBn.png =200x) ---- - #### 常用的 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) 給你滿滿的大平台 ![](https://i.imgur.com/qcRUyfr.jpg) --- ### icon 的使用方式 透過 command 以及多行邊編輯的方式生成 icon ![](https://i.imgur.com/TNtGCXv.png) --- ### 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 的時候也可以切換不同環境變數將程式碼打包 ``` ![](https://i.imgur.com/qs3QbQG.png) ---- [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個欄位的畫面,我要開三隻程式來看狀態改到哪去了 ``` ![](https://i.imgur.com/q4USKHa.png) 😱😱😱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}]"}
    344 views