苹果系统H5下拉加载事件重复触发(react hooks)
文章目录
- 问题描述
- 解决思路
- 引发的问题
- 优化后的代码
问题描述
ios端手机下的h5/小程序,滚动到底部时加载更多数据,但是滚动到底部时重复触发加载事件,在安卓机下则不会发生该问题,记录一下解决方案。
解决思路
为了防止下拉事件重复触发,对下拉事件做一次防抖处理:
import { useState, useRef, useCallback } from 'react';
import debounce from 'lodash/debounce';
const paramPageRef = useRef(1)
const [searchResult, setSearchResult] = useState([]);
// 防抖查询
const debounceSearch = useCallback(
debounce(() => handleSearch (), 300),
[],
);
// 接口查询数据
const handleSearch = async () => {
const params = {
// 一些参数
county: selectedArea.regionName,
address: searchKey,
...stableParams,
currentPage: paramPageRef.current,
};
try {
const res = await fuzzySearchByPage(params);
console.log('addressSearch---response-->', res);
if (res.currentPage === 1) {
setSearchResult(res?.records || []);
} else {
setSearchResult([...searchResult, ...res?.records]);
}
setHasMore(res.hasMore )
paramPageRef.current += 1
} catch (err) {
console.error('handleSearch----err--->', err);
}
};
<ScrollRefresh
down={false}
pull={false}
Lower={() => {
if (hasMore) {
debounceSearch(data)
}
;
}}
/ >
引发的问题
以上代码解决了重复触发下拉到底的问题,但是使用useCallBack的防抖会形成闭包,导致在 handleSearch 方法中取不到最新的 searchResult, 从而加载更多时会少加载前一页的数据,为了防止这个闭包问题,可以通过设置一个新的state,,通过监听这个state触发handleSearch方法。
优化后的代码
import { useState, useRef, useCallback } from 'react';
import debounce from 'lodash/debounce';
const paramPageRef = useRef(1)
const [searchResult, setSearchResult] = useState([]);
const [page, setPage] = useState(1);
// 防抖查询
const debounceSearch = useCallback(
debounce(() => setPage(paramPageRef.current), 300),
[],
);
useEffect(()=>{
console.log(page)
if (page !==1 ) {
handleSearch()
}
},[page])
// 接口查询数据
const handleSearch = async () => {
const params = {
// 一些参数
county: selectedArea.regionName,
address: searchKey,
...stableParams,
currentPage: paramPageRef.current,
};
try {
const res = await fuzzySearchByPage(params);
console.log('addressSearch---response-->', res);
if (res.currentPage === 1) {
setSearchResult(res?.records || []);
} else {
setSearchResult([...searchResult, ...res?.records]);
}
setHasMore(res.hasMore )
paramPageRef.current += 1
} catch (err) {
console.error('handleSearch----err--->', err);
}
};
<ScrollRefresh
down={false}
pull={false}
Lower={() => {
if (hasMore) {
debounceSearch()
}
;
}}
/ >
如此便可以正常请求了,下拉事件在300毫秒内只会触发一次。