本文最后更新于:2022年7月8日 下午
                  
                
              
            
            
              
                
                在 Taro Hooks 出来 之后就一直想着体验一波 Hooks 小程序开发,不过一直忙着补番 😌。最近补完了,就搞了起来,开发了 20 天左右(其实大部分时间都在改 UI😒),基本上是完成了,然后也上架了,遂跟大家分享一点心得 😈
可以先扫描体验:

网络不稳定的小伙伴看预览:

在 GitHub Pro 的开发中,我写了四个 hooks,来帮助我提高开发效率
- useRequest
 
- useRequestWithMore
 
- useReachBottomEvent
 
- usePullDownRefreshEvent
 
接下来就分析一下它们的作用
useRequest
作用同名字,用来进行网络请求,传入请求参数以及进行请求的函数,存储数据,返回 [currData, refresh] ,其中currData是存储的返回数据,refresh用于刷新请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
   | function useRequest<T>(   params: any,   request: (params: any) => Promise<T | null> ): [T | null, () => void] | [] {   const [currData, setData] = useState<T | null>(null)   const [count, setCount] = useState(0)   const pagePullDownRef = useRef('')
    useEffect(() => {     request(params).then(data => {       if (data) {         setData(data)       }     })   }, [count])
    usePullDownRefresh(() => {     refresh()   })
    useEffect(() => {     events.on(PULL_DOWN_REFRESH_EVENT, (page: string) => {       if (!pagePullDownRef.current) {         pagePullDownRef.current = page       } else if (pagePullDownRef.current !== page) {         return       }       refresh()     })     return () => {       events.off(PULL_DOWN_REFRESH_EVENT)     }   }, [])
    const refresh = () => {     setCount(count + 1)   }
    return [currData, refresh] }
  export default useRequest
 
  | 
 
useRequest
useRequestWithMore
这个钩子是最复杂的一个,也是作用最大的一个函数。能够在滚动条到底底部的时候,请求下一页,加载更多的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
   | function useRequestWIthMore<T, S = string>(   data: S,   request: (data: S, params: any | null) => Promise<T[] | null> ): [T[] | null, boolean, () => void, () => void] | [] {   if (!data) {     // bug?     console.warn('useRequestWIthMore: no data')     return []   }
    const [currData, setData] = useState<T[] | null>(null)   const [hasMore, setHasMore] = useState<boolean>(true)   const [params, setParams] = useState(defaultParams)   const loadingRef = useRef(false)
    useEffect(() => {     if (hasMore) {       loadingRef.current = true       request(data, params)         .then(data => {           if (data) {             if (currData) {               setData([...currData, ...data])             } else {               setData(data)             }             if (data.length < params.per_page!) {               setHasMore(false)             }           }         })         .finally(() => {           loadingRef.current = false           Taro.stopPullDownRefresh()           Taro.hideLoading()         })     }   }, [params])
    usePullDownRefresh(() => {     refresh()   })
    useReachBottom(() => {     if (loadingRef.current) {       return     }     getMoreData()   })
    const getMoreData = () => {     setParams(params => ({ ...params, page: params.page! + 1 }))   }
    const refresh = () => {     setData(null)     setHasMore(true)     setParams({ ...params, page: 1 })   }
    return [currData, hasMore, refresh, getMoreData] }
 
  | 
 
是不是很完美,可惜不是这么简单。
Taro 中有个大坑就是在组件中无法使用如usePullDownRefresh、useReachBottom等钩子。
所以就引出来一个大问题 – 如何在组件中触发这些操作呢。而且在 GitHub Pro 中,我把很多组件进行了拆分,难道我要重写?😑
这肯定是不行的。还好贴心的 Taro 给我们提供了一个消息机制(实际上就是发布订阅),可以用它来解决我们当前遇到的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
   | // 存储唯一 id 用于匹配消息  const pageReachBottomRef = useRef('')  const pagePullDownRef = useRef('')
   useEffect(() => {    events.on(REACH_BOTTOM_EVENT, (page: string) => {      if (loadingRef.current) {        return      }      if (!pageReachBottomRef.current) {        pageReachBottomRef.current = page      } else if (pageReachBottomRef.current !== page) {        return      }      getMoreData()    })    return () => {      events.off(REACH_BOTTOM_EVENT)    }  }, [])
   useEffect(() => {    events.on(PULL_DOWN_REFRESH_EVENT, (page: string) => {      if (!pagePullDownRef.current) {        pagePullDownRef.current = page      } else if (pagePullDownRef.current !== page) {        return      }      refresh()    })    return () => {      events.off(PULL_DOWN_REFRESH_EVENT)    }  }, [])
 
  | 
 
其中pageReachBottomRef、pagePullDownRef非常关键,用来对消息进行配对,防止说我这个页面滚动,导致另外一个页面也进行数据的请求。
useRequestWIthMore
usePullDownRefreshEvent
这个钩子用来做当下拉刷时候发送刷新页面的消息(在 page 内使用),而接受者就前面useRequestWithMore了
1 2 3 4 5 6 7 8
   | function usePullDownRefreshEvent() {   const pageRef = useRef(getUniqueId())   usePullDownRefresh(() => {     events.trigger(PULL_DOWN_REFRESH_EVENT, pageRef.current)   })
    return null }
 
  | 
 
usePullDownRefreshEvent
useReachBottomEvent
这个钩子用来做当页面滚动到底部时候发送获取数据的消息(在 page 内使用),而接受者就前面useRequestWithMore了,并且我在内部做了一下节流。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | function useReachBottomEvent() {   const pageRef = useRef(getUniqueId())   const timerRef = useRef(0)
    useReachBottom(() => {     const prev = timerRef.current     const curr = +Date.now()     if (!prev || curr - prev > THROTTLE_DELAY) {       events.trigger(REACH_BOTTOM_EVENT, pageRef.current)       timerRef.current = curr     } else {       console.log('wait...')     }   })
    return null }
 
  | 
 
总结
在 GitHub Pro 开发中,使用 Hooks 能够提高逻辑的复用,大大加快开发的速度,目前我还没有遇到过什么大坑,所以开发体验还是不错的。
推荐资料:
以上我主要讲了如何写 Hooks,而编写之后的使用,可以自行看项目的代码
Repo: zenghongtu/GitHub-Pro