问题描述

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毫秒内只会触发一次。

10-27 12:50