日常踩坑总结
日常项目开发中遇到的 React 相关的各种各样的问题。这里都会以背景、问题、解决方案三块来记录分享给大家,希望自己和其他小伙伴在以后写 BUG 的日子里避免踩相同的坑,
提升开发效率,增加摸鱼时间。持续更新中...
项目技术栈:React、nextjs、useSWR、Parse、TypeScript
Hook 嵌套
列表特殊组件渲染
代码结构设计真的很重要
背景
一个 Table 中的某一列要渲染一个特定组件,这个组件会根据接受的 id 去请求对应的数据用于渲染,然后大列表中会一次发出 pageSize 个请求,不过 id 可能会有重复的,在请求那边,想同的入参会直接返回上次的数据,不会再发真正的请求。
问题
一次性发出多个请求, Chrome http1.1 中一次最多发送 6 条请求,会造成很大的性能问题,这里需要把所有的请求合并,应该一次请求去发送。 理论上应该在父组件上拿到所有的 id 然后去发一个请求的,但结构设计不是每个人都会去深度考虑的,初级开发者在日常工作中可能就是去为了完成需求而开发,不是每个人都会去考虑可用性和可能带来的性能问题。
ps: 没办法改组件,影响太大,时间不够,所以没有把请求拿到父组件去,下边给一个临时解决方案
解决方案
在 useFetchHook 中, 用自定义的 throttle 把请求方法包裹一层,在 wait 时间内,拼接所有请求的参数,之后发出请求,拿到数据,放入 Context 中,期间所有的请求都直接返回 resolve。
/**
* @description 能够缓存参数的节流方法
* @param {function} func 目标方法。间隔时间后,将期间缓存的参数一并传入
* @param {number} wait 间隔毫秒数
* @category 高阶函数
*/
export function genThrottleCacheFunc(func: (arg0: any, arg1?: any) => any, wait: number): any {
let timer: NodeJS.Timeout;
let paramsArr = [];
let result = [];
return async (type: any, params, oldData, setData) => {
paramsArr = union(paramsArr, params);
// 存在回调则返回 Promise.resolve
if (timer) return Promise.resolve();
timer = setTimeout(async () => {
// 单位时间结束后
result = await func.call(this, type, paramsArr);
clearTimeout(timer);
timer = null;
paramsArr = [];
setData(uniqBy([...oldData, ...result], 'id'));
return result;
}, wait);
};
}
// 外层调用直接
const curFetch = genThrottleCacheFunc(fetch, 500)
目前解决方案为这样,后续如果有更好的,会再更新
useMemo & 自定义 Hook
请求参数都要用 useMemo包裹,常量也需要包裹进去
背景
需要改动一个列表中组件的请求方式,通过传入参数的方式区分,且参数固定,所以就在入参的对象中添加了 type: true
感觉上代码比清晰
const ids = useMemo(() => [value].filter(Boolean), [value]);
// 改动前
const {data} = useFetch({ ids })
// 改动后
const {data} = useFetch({ ids, type: true })
问题
在虚拟列表滚动时,渲染过的组件在离开视口后再次进入视口,会再次发起请求。以前是没有的,useFetch 中使用的 useSWR,key 不变会把上次请求的数据返回回来
解决方案
//改动前
const ids = useMemo(() => [value].filter(Boolean), [value]);
const {data} = useFetch({ ids, type: true })
// 改动后
const ids = useMemo(() => [value].filter(Boolean), [value]);
const params = useMemo(() => ({ids, type: true}), [ids])
const {data} = useFetch(params)
闭坑闭坑啊
后续再遇到问题和填的坑都会更新到本文中,不求点赞关注,您阅读到就是我最大的幸运。如果能留下您宝贵的意见或者分享自己遇到过的坑,那将万分感谢!!