在 Taro Hooks 出来 之后就一直想着体验一波 Hooks 小程序开发,不过一直忙着补番 ????。最近补完了,就搞了起来,开发了 20 天左右(其实大部分时间都在改 UI????),基本上是完成了,然后也上架了,遂跟大家分享一点心得 ????
可以先扫描体验:
网络不稳定的小伙伴看预览:
在 GitHub Pro 的开发中,我写了四个 hooks,来帮助我提高开发效率
- useRequest
- useRequestWithMore
- useReachBottomEvent
- usePullDownRefreshEvent
接下来就分析一下它们的作用
useRequest
作用同名字,用来进行网络请求,传入请求参数以及进行请求的函数,存储数据,返回 [currData, refresh]
,其中currData
是存储的返回数据,refresh
用于刷新请求。
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
这个钩子是最复杂的一个,也是作用最大的一个函数。能够在滚动条到底底部的时候,请求下一页,加载更多的数据。
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 给我们提供了一个消息机制(实际上就是发布订阅),可以用它来解决我们当前遇到的问题。
// 存储唯一 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
了
function usePullDownRefreshEvent() { const pageRef = useRef(getUniqueId()) usePullDownRefresh(() => { events.trigger(PULL_DOWN_REFRESH_EVENT, pageRef.current) }) return null}
usePullDownRefreshEvent
useReachBottomEvent
这个钩子用来做当页面滚动到底部时候发送获取数据的消息(在 page 内使用),而接受者就前面useRequestWithMore
了,并且我在内部做了一下节流。
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 · Taro
- 使用 React Hooks 重构你的小程序
以上我主要讲了如何写 Hooks,而编写之后的使用,可以自行看项目的代码
Repo: zenghongtu/GitHub-Pro