您的位置 首页 > 腾讯云社区

useList 列表hook---copy_left

chart.gif

列表是我们日常开发中经常会碰到的一类展示形式, 只是以不同的 UI 显示在用户面前,例如: 菜单,表格等,其中一些操作, 加载,重置,等是基本相同的,所以我们希望抽离这部分公共逻辑, 这里记录使用hook封装时碰到的一些问题

功能设置查询参数设置初始列表值请求列表,叠加数据请求列表,重置数据实现import React, { useState, useCallback, useRef } from 'react'; async function asyncVessel(promise) { return promise.then(res => [res, null]).catch(err => [null, err]) } /** * 列表请求hook * @param { Function } requery 请求函数 * @param { Object } initQuery 初始查询参数 * @param { Array } initList 初始列表 * @returns { Array } * - list 当前列表 * - util * - reset 重置设置爱 * isEnd 是否已获取所有数据 * loadList 请求列表,叠加 * query 查询数据 state * currentQuery 查询数据 ref * reloadList 请求类表, 重置 * updateQuery 更新查询数据 * * * @example * * const [ list, util ] = useList( load, { sort: 1, type: 2, pageNo: 0, pageSize: 10 } ) * * 模板 * * <div> * * <SearchBar onSearch={ util.reloadList } ></SearchBar> * * <List> * { list.map(item => <List-item :key={item.id} > { ... } </List-item> ) } * </List> * </div> * */ function useList(requery, initQuery, initList=[]){ const [ list, setList ] = useState(initList) const [ isEnd, setEnd ] = useState(false) const [ query, setQuery ] = useState(initQuery) const [ queryCache, setQueryCache ] = useState(initQuery) const currentQuery = useRef(initQuery) const updateQuery = useCallback( data => { currentQuery.current = { ...currentQuery.current, ...data } setQuery( prev => ({...prev, ...data}) ) }, [ query, setQuery ] ) // 请求列表,叠加数据 const loadList = useCallback( async () => { if(isEnd) return currentQuery.current = { ...currentQuery.current, pageNo: currentQuery.current.pageNo + 1 } const [ res, err ] = await asyncVessel(requery(currentQuery.current)) if(err) return updateQuery(currentQuery.current) setEnd( !res.result || !res.result.length) setList( prev => [ ...prev, ...res.result ] ) }, [ isEnd, setEnd, setList, requery ]) // 请求列表, 重载数据 const reloadList = useCallback( async () => { setEnd(false) updateQuery({ pageNo: 1 }) setList([]) const [ res, err ] = await asyncVessel(requery(currentQuery.current)) if(err) return setList( [...res.result] ) }, [ isEnd, setEnd, setList, requery ]) // 重置设置 const reset = useCallback( () => { setEnd(false) updateQuery(queryCache) }, [ setEnd, updateQuery , queryCache] ) const util = { reset, isEnd, loadList, query, currentQuery, reloadList, updateQuery } return [ list, util ] } export default useList问题1 如何设置及更新请求参数 const [ query, setQuery ] = useState(initQuery) const [ queryCache, setQueryCache ] = useState(initQuery) const currentQuery = useRef(initQuery)

可以看到这里设置了三类 query, quryCache 用户重置参数, query 用于更新视图, currentQuery 用于获取最新参数. 这样设置的原因需要结合请求及参数的更新来看

分页数更新 // 请求数据 const [ res, err ] = await asyncVessel(requery(currentQuery.current)) if(err) return updateQuery(currentQuery.current) // 更新 query setEnd( !res.result || !res.result.length) setList( prev => [ ...prev, ...res.result ] )

这里会在请求完成后更新查询参数,主要为了统一分页数,为什么要在请求完成后更新分页数呢?请求新的分页数据前,分页数都是需要自增的, 设想如果我们在请求前更新分页数,而此时请求失败。用户再次请求数据时,将跳过前一次失败的数据。

参数修改

QQ截图20200410191441.png

通常参数的修改也是用户交互的一部分, 简单的通过表单或开关修改, 这是我们需要将参数与组件绑定在一起,但这时就会遇到一个问题。 修改参数后如何更新列表

// setQuery 更新数据是一个异步的过程,通过设置参数后直接调用load,并不可靠 const [ query, setQuery ] = useState({....}) loadList(query) // 这样只能拿到旧的query值// 通过 useEffect useEffect( () => { loadList( query ) }, [ query.sort ] ) // 这样可以获取到 query 最新的值,但丢失了主动触发请求的能力。 // 并不是每次查询数据的更新都需要列表数据。 // 如果使用中间变量做缓存,那内置query state 就没有多大意义了。useRef 与 useState 的区别// useState const [ query, setQuery ] = useState(initQuery) // 每次更新 返回新的 query, setQuery // useRef const currentQuery = useRef(initQuery) // 始终返回同一对象

除了返回值不同外,主要的区别有两点

useState 每次更新都返回新的值, useRef 始终指向同一对象。useState 的值更新将触发视图更新, useRef 不会触发关联视图的更新。// 封装参数更新函数 const updateQuery = useCallback( data => { currentQuery.current = { ...currentQuery.current, ...data } setQuery( prev => ({...prev, ...data}) ) }, [ query, setQuery ] )

正式因为前面的特点,所以独立封装了参数的更新函数,同时更新currentQuery, query 保证取值及视图展示。

问题2 依赖

react hook 与 vue hook 明显的区别之一,react 需要我们手动关联并处理依赖,保证取值的正确及效率.

// 使用useCallback 只在关联依赖更新时,更新函数。 const reloadList = useCallback( async () => { setEnd(false) updateQuery({ pageNo: 1 }) setList([]) const [ res, err ] = await asyncVessel(requery(currentQuery.current)) if(err) return setList( [...res.result] ) }, [ isEnd, setEnd, setList, requery ]) // setState 函数也在依赖范围内深入理解:React hooks是如何工作的?left-vue-hooks vue的hooks工具包 ---来自腾讯云社区的---copy_left

关于作者: 瞎采新闻

这里可以显示个人介绍!这里可以显示个人介绍!

热门文章

留言与评论(共有 0 条评论)
   
验证码: