react-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)

分析

分析要封装的代码逻辑,找到相同点和不同点。
函数封装的基本思想:将相同的逻辑直接拷贝到函数中,不同的逻辑通过函数参数传入。需要返回数据,就通过函数返回值返回。

  1. 相同点

    有以下相同代码

  1. 不同点

    1. 需要派发的函数不同
    2. 需要返回的状态不同
  2. 结论

    1. 自定义hooks的参数就是需要派发的函数和需要返回的状态名

    2. 自定义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版本–有类型约束

  1. 参数 action:
  • 就是一个函数,所以,直接指定为最简单的函数类型即可
  1. 参数 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 (
  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')