遇到这样一种工作场景:当一个页面需要依赖多个请求并发处理时,而显示数据需要实时变动(根据传入的参数变动而实时更改)
起初我没有想到那么多时我是这样写的
const escortExperienceParm = useSelector((state: RootState) => state.escortExperienceParam); //伴游经验参数
const escortSumParm = useSelector((state: RootState) => state.escortSum); //伴游总数据
const escortTipParm = useSelector((state: RootState) => state.escortTip); //伴游打赏参数
const escortRewar = useSelector((state: RootState) => state.escortRewar); //伴游报酬参数
const escortNumOrder = useSelector((state: RootState) => state.escortNumOrder);
const escortType = useSelector((state: RootState) => state.escortType);
// 定义状态和数据获取
const [escortSumData, setEscortSumData] = useState<TableDataRes>();
const [experienceData, setExperienceData] = useState<TableDataRes>();
const [escortTiData, setEscortTipData] = useState<TableDataRes>();
const [rewardData, setRewardData] = useState<TableDataRes>();
const [numOrderData, setNumOrderData] = useState<TableDataRes>();
const [escortTypeData, setEscortTypeData] = useState<TableDataRes>();
useEffect(() => {
const fetchData = async () => {
try {
setEscortSumData(await escortGetAccompanyTravelData(escortSumParm));
setEscortTipData(await escortGetAccompanyTravelGift(escortTipParm));
setRewardData(await escortGetGetFee(escortRewar));
setNumOrderData(await escortGetPublicAndTarget(escortNumOrder));
setEscortTypeData(await escortGetType(escortType));
} catch (error) {
console.error('Error fetching data', error);
}
};
fetchData();
}, [escortSumParm, escortExperienceParm, escortTipParm,escortType,escortNumOrder]);
首先我需要取到redux状态参数,然后定义页面状态,然后在根据参数获取数据再更改状态。这时我注意到这个场景我会多次这样使用,会不会有胆太复杂了。而且好像依赖的参数一变动所有的数据重新请求?这样不对!
第一种解决方法:每个请求使用一个useEffect,依赖各自的参数.。(这样问题可以解决,但是正如我刚才所说,这个会是个多场景业务,,业务问题得以解决,但是代码重复会特别多。)果断舍弃这种方案。
仔细想想可不可以封装一个请求函数,传入一个请求api和参数,参数变化是自动执行函数?可行!开搞
import { useEffect, useState } from 'react';
/**
* 自定义钩子用于处理异步数据请求
* @param asyncFunction - 执行异步操作的函数
* @param dependencies - 依赖数组,决定何时重新执行异步操作
* @returns 包含数据、加载状态和错误信息的对象
*/
const useAsyncEffect = (asyncFunction: () => Promise<any>, dependencies: any[]) => {
const [data, setData] = useState<any>(undefined);
useEffect(
() => {
let isMounted = true;
asyncFunction().then(result => {
if (isMounted) {
setData(result);
}
});
return () => {
isMounted = false;
};
},
dependencies
);
return data;
};
export default useAsyncEffect;
这样简单的封装了一下useEffect,代码结构比较简单不做过多解释。
实事实上这个有个bug,这里如果依赖项是个简单数据类型监听到自动触发,可如果是个引用数据类型呢?实际上useEffect它只是浅层监听,该如何解决呢?这有涉及到深浅拷贝的知识面了,解决方案如下
// 使用 JSON.stringify 序列化依赖项
},
dependencies.map(dep => JSON.stringify(dep))
到此函数封装结束接下来看我简化后的代码
const escortExperienceParm = useSelector((state: RootState) => state.escortExperienceParam); //伴游经验参数
const escortSumParm = useSelector((state: RootState) => state.escortSum); //伴游总数据
const escortTipParm = useSelector((state: RootState) => state.escortTip); //伴游打赏参数
const escortRewar = useSelector((state: RootState) => state.escortRewar); //伴游报酬参数
const escortNumOrder = useSelector((state: RootState) => state.escortNumOrder);
const escortType = useSelector((state: RootState) => state.escortType);
const escortSumData = useAsyncEffect(() => escortGetAccompanyTravelData(escortSumParm), [escortSumParm]);
const experienceData1 = useAsyncEffect(() => escortGetExperience(escortExperienceParm), [escortExperienceParm]);
const escortTiData = useAsyncEffect(() => escortGetAccompanyTravelGift(escortTipParm), [escortTipParm]);
const rewardData = useAsyncEffect(() => escortGetGetFee(escortRewar), [escortRewar]);
const numOrderData = useAsyncEffect(() => escortGetPublicAndTarget(escortNumOrder), [escortNumOrder]);
const escortTypeData = useAsyncEffect(() => escortGetType(escortType), [escortType]);
依然需要取到redux的状态,但是后续就不会有过多的定义修改操作了。最后关于这个方法如果你有更好的解决方法的话请指出,我们一起讨论