You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React搜索滚动加载时修改查询文本结果数组未重置怎么解决

问题根因
  • 没有区分「新搜索」和「滚动加载下一页」两种场景,所有请求都走了结果追加逻辑,且更换搜索词时没有清空历史结果、重置页码为1
  • 输入框onChange每输入一个字符就触发搜索,无防抖逻辑会导致请求混乱
  • 状态更新存在闭包陷阱,请求逻辑依赖的外部状态没有正确处理
修复步骤
  1. 新增标识区分请求类型,新搜索时清空历史结果、重置页码,加载更多时才追加结果
  2. 给搜索输入加防抖,避免频繁触发请求
  3. 修正滚动逻辑,避免重复请求和闭包问题
修复后完整代码
import React, { useState, useCallback } from 'react';
import axios from 'axios';
import styled from 'styled-components';

const SearchStickerContainer = styled.div`
    width: 100%;
    height: 70vh;
    overflow: scroll;
    position: absolute;
    top: 20%;
`;

const SearchLabel = styled.label`
    font-size: 25px;
    font-weight: bold;
`;

// 防抖工具函数
function debounce(func, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

function SearchStickers() {
    const [photos, setPhotos] = useState([]);
    const [page, setPage] = useState(1);
    const [isLoading, setIsLoading] = useState(false);
    const [query, setQuery] = useState('');

    // 搜索请求逻辑,isNewSearch标记是否是新搜索
    const querySearch = useCallback(async (queryString, pageNum, isNewSearch = false) => {
        if (!queryString.trim() || isLoading) return;
        setIsLoading(true);
        
        const config = {
            headers: {
                apiKey: '823bb74a52fb44f8590c87b3dfd8c4e8'
            }
        };

        try {
            const res = await axios.get(
                `/v1/search?userId=9937&q=${queryString}&lang=en&pageNumber=${pageNum}&limit=20`,
                config
            );
            const stickerList = res.data.body.stickerList || [];
            if (isNewSearch) {
                // 新搜索直接替换结果
                setPhotos(stickerList);
                setPage(1);
                // 滚动到顶部展示新结果
                document.querySelector('#sticker-container')?.scrollTo(0, 0);
            } else {
                // 加载更多追加结果
                setPhotos(prev => [...prev, ...stickerList]);
                setPage(prev => prev + 1);
            }
        } catch (err) {
            console.error('搜索失败', err);
        } finally {
            setIsLoading(false);
        }
    }, [isLoading]);

    // 防抖处理搜索请求
    const debouncedSearch = useCallback(
        debounce((searchVal) => querySearch(searchVal, 1, true), 300),
        [querySearch]
    );

    const handleInputChange = (e) => {
        const value = e.target.value;
        setQuery(value);
        debouncedSearch(value);
    };

    const handleScroll = (e) => {
        const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
        if (bottom && !isLoading && query.trim()) {
            querySearch(query, page + 1, false);
        }
    };

    return (
        <SearchStickerContainer id="sticker-container" onScroll={handleScroll}>
            <form onSubmit={(e) => e.preventDefault()}>
                <SearchLabel>
                    <span>search</span>
                </SearchLabel>
                <input 
                    type="text"
                    id="search"
                    placeholder="search stickers"
                    onChange={handleInputChange}
                    value={query}
                />
            </form>
            <div>
                <div style={{ minHeight: "100px" }}>
                    {photos.map((sticker, idx) => (
                        <img key={idx} src={sticker.stickerImg} height="200px" width="200px" alt="sticker" />
                    ))}
                </div>        
                {isLoading ? <div> Loading ... </div> : null}            
            </div>
        </SearchStickerContainer>
    );
}

export default SearchStickers;
核心修改说明
  • 新增isNewSearch参数:新搜索时直接替换photos数组,不会追加历史结果,同时自动滚动到容器顶部,不用手动下拉查看新结果
  • 新增防抖逻辑:输入结束后300ms才发起请求,避免频繁触发接口调用
  • 修正滚动加载逻辑:只有在非加载状态、有搜索词、滚动到底部时才触发下一页加载,避免重复请求
  • 移除无用状态:删除了冗余的bottom、search状态,简化逻辑

内容的提问来源于stack exchange,提问作者SoftJellyfish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 10:27:00