react-hooks封裝-傳送請求初始化
阿新 • • 發佈:2022-04-04
hooks封裝-傳送請求初始化
使用技術為
redux
+(ts
/js
)
因傳送請求獲取資料的邏輯基本一致,所以將其封裝為自定義hooks,用以簡化程式碼
檢查
首先檢查原始碼,兩段程式碼的邏輯相同,都是用dispatch派發請求,然後使用useSelect獲取store中的資料。
`Profile.tsx` const dispatch = useDispatch() useEffect(() => { dispatch(getUser()) }, [dispatch]) const user = useSelector((state: RootState) => state.profile.user) `Edit.tsx` const dispatch = useDispatch() useEffect(() => { dispatch(getUserProfile()) }, [dispatch]) const userProfile = useSelector((state: RootState) => state.profile.userProfile)
分析
分析要封裝的程式碼邏輯,找到相同點和不同點。
函式封裝的基本思想:將相同的邏輯直接拷貝到函式中,不同的邏輯通過函式引數傳入。需要返回資料,就通過函式返回值返回。
-
相同點
有以下相同程式碼
-
不同點
- 需要派發的函式不同
- 需要返回的狀態不同
-
結論
-
自定義hooks的引數就是需要派發的函式和需要返回的狀態名
-
自定義hooks的返回值就是需要返回的狀態
-
所以得到以下簡易程式碼
const useInitialState = (action, stateName) => { // 需要複用的狀態邏輯程式碼 return state } // 使用自定義 hooks: const { userProfile } = useInitState(getUserProfile, 'profile') const { user } = useInitialState(getUser, 'profile')
優化
js版本–無型別約束
將相同的邏輯,直接封裝到 useInitState 函式中
useInitState.ts
// 匯入依賴的包 import { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { RootState } from '@/types/store' // action:需要派發的函式名 stateName:需要獲取的狀態名 return狀態值 export default function useInitialState (action, stateName) { const dispatch = useDispatch() useEffect(() => { dispatch(action()) }, [dispatch]) return useSelector((state:RootState) => state[stateName]) }
ts版本–有型別約束
- 引數 action:
- 就是一個函式,所以,直接指定為最簡單的函式型別即可
- 引數 stateName:
- stateName 表示從 Redux 狀態中取出的狀態名稱,比如,
'profile'
- 所以,stateName 應該是 RootState 中的所有狀態名稱中的任意一個
useInitState.ts
// 1. 泛型K 繼承自RootState 的key 值
// 2. RootState 為store 狀態的匯流排
// 3. keyof 獲取RootState 的所有狀態名的型別
// 4. 將K 賦值給stateName 的狀態
// 5. 返回相應狀態名的值
// action:需要派發的函式名 stateName:需要獲取的狀態名 return狀態值
export default function useInitialState<K extends keyof RootState> (
action: () => void,
stateName: K
) {
const dispatch = useDispatch()
useEffect(() => {
dispatch(action())
}, [dispatch])
return useSelector((state: RootState) => state[stateName])
}
使用
Edit.tsx
import { useInitState } from '@/hooks/useInitState'
const { userProfile } = useInitState(getUserProfile, 'profile')