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

React JS中如何在搜索进行时显示Spinner加载动画

问题分析
  • 你的代码中连续同步调用setIsSearching(true)和setIsSearching(false),React的状态更新是批量异步处理的,这两次更新会被合并,最终isSearching直接变为false,Spinner没有触发渲染的机会
  • 缺少实际的搜索逻辑绑定,加载状态没有和搜索的执行周期挂钩,相当于开启加载后立刻关闭,自然看不到效果
正确实现方案

加载状态需要和搜索的完整执行周期绑定,在搜索开始前设为true,搜索结束(无论成功失败)后再设为false,以下是适配不同场景的实现方式:

1. 异步接口搜索(最常见场景)

适用于需要调用后端接口获取搜索结果的情况:

import { useState, useCallback } from 'react';
// 假设你已正确引入Input、Spinner组件

const [isSearching, setIsSearching] = useState(false);
const [searchValue, setSearchValue] = useState('');
const [searchResult, setSearchResult] = useState([]);

// 封装实际搜索请求逻辑
const fetchSearchResult = useCallback(async (keyword) => {
  // 替换为你的真实接口请求
  const res = await fetch(`/api/search?q=${encodeURIComponent(keyword)}`);
  return await res.json();
}, []);

const handleSearch = useCallback(async (e) => {
  const keyword = e.target.value;
  setSearchValue(keyword);

  // 空关键词直接重置
  if (!keyword.trim()) {
    setSearchResult([]);
    return;
  }

  // 搜索开始前开启加载
  setIsSearching(true);
  try {
    const result = await fetchSearchResult(keyword);
    setSearchResult(result);
  } catch (err) {
    console.error('搜索失败:', err);
  } finally {
    // 无论请求成功/失败,都关闭加载状态
    setIsSearching(false);
  }
}, [fetchSearchResult]);

// 渲染逻辑
return (
  <div>
    <Input onChange={handleSearch} value={searchValue} />
    <Spinner style={{ display: isSearching ? 'block' : 'none' }} />
    {/* 渲染搜索结果 */}
    {!isSearching && searchResult.map(item => (
      <div key={item.id}>{item.content}</div>
    ))}
  </div>
)

2. 实时输入搜索场景

如果是输入时实时触发搜索,建议添加防抖逻辑,避免频繁触发请求和加载闪烁:

import { debounce } from 'lodash';
// 也可以自行实现防抖函数

// 用防抖包装搜索逻辑,用户停止输入300ms后再发起请求
const debouncedFetch = useCallback(
  debounce(async (keyword) => {
    setIsSearching(true);
    try {
      const result = await fetchSearchResult(keyword);
      setSearchResult(result);
    } finally {
      setIsSearching(false);
    }
  }, 300),
  [fetchSearchResult]
);

const handleInputChange = (e) => {
  const keyword = e.target.value;
  setSearchValue(keyword);
  if (!keyword.trim()) {
    setSearchResult([]);
    setIsSearching(false);
    return;
  }
  debouncedFetch(keyword);
};

3. 本地同步搜索场景

如果是搜索前端已有的本地数据,本身耗时极短,通常不需要展示Spinner。如果一定要展示,可以加最小展示时长避免闪一下就消失:

const handleLocalSearch = async (keyword) => {
  setIsSearching(true);
  // 用Promise.all保证Spinner至少展示300ms
  const [result] = await Promise.all([
    new Promise(resolve => {
      // 你的本地搜索逻辑
      const res = localData.filter(item => item.title.includes(keyword));
      resolve(res);
    }),
    new Promise(resolve => setTimeout(resolve, 300))
  ]);
  setSearchResult(result);
  setIsSearching(false);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:54:04