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

React Hooks实现带Debounce的搜索框:技术问题咨询

React自动完成组件问题解答

原代码

import React, { useEffect, useState } from 'react'
import axios from 'axios'

function AutoCompleteInput() {

    const[data,setData] = useState([])
    const [filtereddata,setfilteredData]=useState([])

    useEffect(()=>{
      const Timer = setTimeout(()=>{
        axios.get('https://jsonplaceholder.typicode.com/users')
            .then((res)=>{
              //console.log(res.data[0])
                setData(res.data)
                setfilteredData(res.data)
            })
            .catch((err)=>console.log("some error"))

      },2000)
      
      return()=>clearTimeout(Timer)  
      
    },[data])
    

    const handleChange=(searchvalue)=>{
       // console.log(value)
      
        const filteritems= filtereddata.filter(item=>item.name.toLowerCase().includes(searchvalue))
       //console.log(filteritems)
         setData(filteritems)
      
     }
  return (
    <div>
         <input type="text" placeholder="search here..." onChange={(e)=>handleChange(e.target.value)}/>
        <div>
            <table>
                <thead>
                    <tr>
                    <th>name</th>
                       <th>username</th>
                        <th>email</th>
                         <th>phone</th>
                    </tr>
                      
                </thead>
                   
                <tbody>
                {data.map((d,i)=>{
                        return (
                            <tr key={i}>
                             <td>{i+1}</td>
                              <td>{d.name}</td>
                               <td>{d.username}</td>
                               <td>{d.email}</td>
                               <td>{d.phone}</td>
                            </tr>
                            )
                    })}
                </tbody>
                 
            
            </table>
        </div>
    </div>
  )
}
export default AutoCompleteInput

问题解答

1. useEffect依赖数组配置问题

你把[data]作为依赖数组,会导致每次data变化(比如搜索过滤后),useEffect重新执行,再次请求API并将data和filtereddata重置为完整用户列表,这就是搜索后又恢复全量数据的原因。

正确配置是依赖数组设为空数组[],这样useEffect只会在组件首次挂载时执行一次,初始化全量数据,后续不会因data变化重复触发:

useEffect(()=>{
  const Timer = setTimeout(()=>{
    axios.get('https://jsonplaceholder.typicode.com/users')
        .then((res)=>{
          setData(res.data)
          setfilteredData(res.data)
        })
        .catch((err)=>console.log("some error"))

  },2000)
  
  return()=>clearTimeout(Timer)  
  
},[]) // 改为空数组

2. 搜索防抖与数据展示问题

你目前的2秒定时器是加在初始化API请求上,不是搜索的防抖逻辑,导致两个问题:

  • 初始化数据要等2秒才加载,这段时间输入搜索内容时,filtereddata还是空数组,过滤结果自然为空
  • 没有对搜索输入做防抖,每次输入都会立刻触发过滤(若后续改成后端搜索,会产生频繁请求)

解决步骤:

  1. 调整初始化请求的延迟:如果不需要刻意延迟加载,直接去掉setTimeout,让数据尽快加载:

    useEffect(()=>{
      axios.get('https://jsonplaceholder.typicode.com/users')
          .then((res)=>{
            setData(res.data)
            setfilteredData(res.data)
          })
          .catch((err)=>console.log("some error"))
    },[])
    
  2. 给搜索输入添加防抖:
    用useCallback结合定时器实现防抖,避免输入过程中频繁触发过滤:

    import React, { useEffect, useState, useCallback } from 'react'
    import axios from 'axios'
    
    function AutoCompleteInput() {
      const[data,setData] = useState([])
      const [filtereddata,setfilteredData]=useState([])
      const [searchValue, setSearchValue] = useState('') // 新增状态存储搜索值
    
      // 防抖处理的过滤函数
      const debouncedFilter = useCallback(() => {
        const filterItems = filtereddata.filter(item => 
          item.name.toLowerCase().includes(searchValue.toLowerCase())
        )
        setData(filterItems)
      }, [searchValue, filtereddata])
    
      useEffect(() => {
        const timer = setTimeout(debouncedFilter, 300) // 300ms防抖延迟
        return () => clearTimeout(timer)
      }, [debouncedFilter])
    
      const handleChange=(value)=>{
        setSearchValue(value)
      }
    
      // 初始化请求部分改为空数组依赖
      useEffect(()=>{
        axios.get('https://jsonplaceholder.typicode.com/users')
            .then((res)=>{
              setData(res.data)
              setfilteredData(res.data)
            })
            .catch((err)=>console.log("some error"))
      },[])
    
      // ...返回部分代码不变
    }
    export default AutoCompleteInput
    

另外注意:你代码里表格thead的列数(4列)和tbody的列数(5列)不匹配,建议调整thead加上序号列,或者去掉tbody的序号列,避免布局错乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:27:06