前言:这里是一个菜鸡前端,一直都有想法写写文章,想要一点一点进步,但是不知道要写点什么。想来想去还是记录一下遇到的问题,还有解决的思路。有更好的思路或者不同的方法,欢迎大家交流。
背景:之前在做小程序开发时,在预约管理中有多个tab,在不同tab切换时,列表的内容也会根据tab变化。测试当时提了一个bug,表示在来回切换tab时,不同的tab中的数据会互相串。当时大致的逻辑如下:
const [dataSource, setDataSource] = useState([]);
const fetch = async (type) => {
const res = await getData(type);
setDataSource(res?.data || []);
}
useEffect(()=>{
fetch(type);
}, [type])
return (
<View>
<Tabs {...tabProps} />
<View>
{dataSource.map((item) => (<Item {...item}/>))}
</View>
</View>
)
然后查了一下,看到了network中先发送的请求后到达,这就会导致dataSource会被覆盖掉,所以数据就串了。
解决思路:询问了一下公司的前辈,他说这类问题的话,可以在请求发出去的时候记录一个id,如果请求时的id和记录的id不一致的话,就不做处理,改动后如下:
const [dataSource, setDataSource] = useState([]);
const requestIdRef = useRef(null);
const fetch = async (type) => {
const id = generateId();
requestIdRef.current = id
const res = await getData(type);
if(requestIdRef.current !== id) {
return;
}
setDataSource(res?.data || []);
}
useEffect(()=>{
fetch(type);
}, [type])
return (
<View>
<Tabs {...tabProps} />
<View>
{dataSource.map((item) => (<Item {...item}/>))}
</View>
</View>
)
这么一来确实处理了这个问题。但是还有许多场景也是类似的,如果后续还有类似的场景,这种代码不得每次都写一遍?于是冒出来一个想法,写一个hook来处理,就叫它useNewestRequest好了(随便取
实现:实现的思路倒是没有什么变化,依旧是通过记录id来进行区分,最后通过返回一个方法来进行调用。以下是实现:
const useNewestRequest = ({ request, onSuccess, onError }) => {
const requestId = useRef(null);
/**
* 接口调用方法
* @param {接口传参} params
* @param {额外的传参,会原封不动地回调返回回去} args
* @returns
*/
const run = async (params, ...args) => {
const newId = generateId();
requestId.current = newId;
const res = await request(params).catch((err) => {
onError?.(err);
});
if (!res) {
return;
}
if (requestId.current !== newId) {
return;
}
onSuccess?.(res, ...args);
};
return { run };
};
至于使用嘛,针对上面的例子就可以这样改造:
const [dataSource, setDataSource] = useState([]);
const { run } = useNewestRequest({
request: getData,
onSuccess: (res) => {
setDataSource(res?.data || []);
},
onError: () => {
setDataSource([]);
}
})
useEffect(()=>{
run(type);
}, [type])
return (
<View>
<Tabs {...tabProps} />
<View>
{dataSource.map((item) => (<Item {...item}/>))}
</View>
</View>
)
这样一来就搞定了!
后记:希望以此为契机,能够再多记录一些问题,多写一些文章,记录自己的成长过程。