乐趣区

使用-Taro-Hooks-快速开发一个小程序-GitHub-Pro

在 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 中有个大坑就是在组件中无法使用如 usePullDownRefreshuseReachBottom 等钩子。

所以就引出来一个大问题 — 如何在组件中触发这些操作呢。而且在 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)
    }
  }, [])

其中 pageReachBottomRefpagePullDownRef 非常关键,用来对消息进行配对,防止说我这个页面滚动,导致另外一个页面也进行数据的请求。

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

退出移动版