Skip to main content

2-6


useSelector

const post = useSelector(state => state.user.posts.find(post => post.id === id)))
// state.user 的 user 為該 slice 的名稱,slice 為 Redux 官方定義用來區別不同的 store 資料
  • useSelector(func),傳入一個 callback fuction,callback fuction 會取得的第一個參數是 state,用來取得 store 裡的資料。
  • 每次有 action disaptched 時,useSelector 都會重新執行一遍 (就算是不同的 slice 都會)
  • 若應用越來越大,每次有 action disaptched 時想必會讓各處很多的 useSelector 重新計算,故可以用 createSelector 來建立一個 memoized selector

createSelector

// 建立 memoized selector
const selectPostsByUser = createSelector(
[selectAllPosts, (state, userId) => userId],
(posts, userId) => posts.filter(post => post.user === userId)
)
// 組件內使用
const postsForUser = useSelector(state => selectPostsByUser(state, userId))
  • createSelector 第一個參數為陣列,陣列內需為 function,稱為 input selector,call selectPostsByUser 時所傳入的參數,會傳入每個 input selector ,意指每個 input selector 取得的參數都一樣,接著根據每個 input selector 得出的值,會傳入 createSelector 的第二個參數 output selector function 內,output selector 取得 input selector 得出的值做運算並回傳結果。
  • 此 memoized 重點在於呼叫 selectPostsByUser 時傳入的值前後是否一樣,或是 input selector 回傳的值前後是否一樣,若都相同則 useSelector 會回傳上次的計算結果。
  • 上述再補充:呼叫 selectPostsByUser 時傳入的值若前後不一樣則會跑 input selector, input selector 回傳的值若前後不一樣則會跑 output selector。其中某個階段的結果值前後一樣就會回傳上次最終的計算結果。

shallowEqual

import { shallowEqual, useSelector } from 'react-redux'
// later
const selectedData = useSelector(selectorReturningObject, shallowEqual)
  • useSelector 可傳入第二個參數,shallowEqual 用於比對 selectorReturningObject 回傳的值是否淺相等,經常使用在 若 selector 計算過後會回傳新的 reference 物件,由於前後值一定不一樣故 selectedData 一定會變,此 shallowEqual 就是只淺比對回傳的物件前後是否一樣 (不看reference),若一樣則回傳上次的舊的 reference 物件。

craco

  • Create React App Configuration Override,使用 create react app 建立專案後,若是要自訂 webpack 相關配置,則可以安裝 @craco/craco,並在根目錄新增 craco.config.js 即可在裡面寫配置。
  • 並在 package.json 改成使用 craco 指令。
/* package.json */

"scripts": {
// "start": "react-scripts start",
"start": "craco start",
// "build": "react-scripts build",
"build": "craco build",
// "test": "react-scripts test",
"test": "craco test"
}

@ path alias in React

/* craco.config.js */
module.exports = {
webpack: {
alias: {
'@': path.resolve(__dirname, 'src/'),
'@components': path.resolve(__dirname, 'src/components/'),
'@images': path.resolve(__dirname, 'src/assets/images/'),
'@styles': path.resolve(__dirname, 'src/styles/')
}
}
}
  • 方便在引入常用的資料夾檔案

git revert -m

git 修改 commit 訊息

  • git commit —amend,修改最近提交的一次 commit 訊息。
  • git push --force-with-lease <遠端儲存庫別名> <分支名稱>,將更改推送到遠端儲存庫。
  • --force-with-lease 可避免執行時,若有其他人在對遠端儲存庫存取,對資料造成損毀。

Jest

  • toBe 是用 Object.is 檢查是否相等(包含參考),toEqual 是檢查值是否相等(不檢查參考)。
  • test.only 可以讓該檔案只跑該 test,在 trace test failed 原因時很有用。

Jest Asynchronous Code

測試非同步的函式有三種方式,callback、Promise.then().catch、async await。 個人較常與偏好使用 async await 故擷取該範例:

test('the data is peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
// 使用此語法給定這個 test 預計要有幾個 expect 執行,若沒有這個,fetchData fullfilled 時將會通過測試
expect.assertions(1);
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
}
});
  • 使用 callback 或其他需要等待的測試時,給 test 的 callback function 可以接 done 的參數,可用來在完成時呼叫 done()
  • 接 done 的參數卻沒有使用時,預設是等5秒後會 failed test
  • 測試 Promise.then().catch 非同步函式時,需要 return 該 Promise

Jest Setup and Teardown

在一些情境下,需要在跑該測試前先建立一些資料等等,可以用下列方法建立:

  • 在每個 test 前都做一次
beforeEach(() => {
initializeCityDatabase();
});

afterEach(() => {
clearCityDatabase();
});
  • 在該檔案內跑 test 前,做一次
beforeAll(() => {
return initializeCityDatabase();
});

afterAll(() => {
return clearCityDatabase();
});

Scoping

  • 使用 describe function 將 test 包含在內,形成一個 scope,在此 describe 內的 before & after 系列都只會作用在此範圍內。
  • top-level 的 before 會優先執行,after 會最後執行。
  • describe 會全部都跑過一次,才會跑 test

it & test


bash

  • bash v4 以後才有 declare -a 參數可以用
  • 查詢版本:bash —version
  • declare [-afFirtx] [-p] [name[=value] ...]

encodeURIComponent()

  • 將字串轉換成 UTF-8 編碼
console.log(`${encodeURIComponent('?=/&;')}`)
console.log(`${encodeURIComponent('哈囉')}`)
`// "%3F%3D%2F%26%3B"
// "%E5%93%88%E5%9B%89"`
  • 不轉換符號包括:A-Z a-z 0-9 - _ . ! ~ * ' ( )

decodeURIComponent()

  • encodeURIComponent() 相反

encodeURI()

  • 將字串轉換成 UTF-8 編碼
  • 一般情況下最好使用 encodeURIComponent()
  • encodeURI() 產生的編碼不適用於 HTTP 請求的 uri,因為其不轉換符號在 HTTP 請求中需要被編碼,例如:&、?
  • 不轉換符號包括:* A-Z a-z 0-9~!@#$&()=:/,;?+'

decodeURI()

  • encodeURI() 相反

axios content type


How to do things

  1. Write jest test
  2. Read and run every example in the documents
  3. Follow the convention from the environment e.g. instead of using redux starter kit, check what your company is using
  4. If you want to master a thing, you have to sacrifice other things e.g. time for using facebook, etc
  5. How to estimate target salary based on pension
  6. Goal and direction should match
  7. Learn things with a longer lifetime, e.g. computer science > programming language > library > framework
  8. Learning by listening to others is less efficient than learning by yourself
  9. Program design is subjective, however, most programmer would agree to DRY and SoC
  10. Context is everything
  11. Limitation forces creativity
  12. Focus on one single thing at a time
  13. KISS
  14. SMART
  15. Be aware of vendor-lock in
  16. Find and fill knowledge gap
  17. Every line of of code has to have a reason, a reason has to convince others