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

输入搜索内容时useList钩子重复执行的问题及解决方法

解决方案

1. 缓存useList中的计算结果

每次组件重渲染时,你的useList都会重复执行_.cloneDeep和filter操作,生成全新的list和otherMenus对象——这不仅是无意义的重复计算,还可能触发额外的组件重渲染。用useMemo缓存这些计算结果,只有当依赖的data变化时才重新计算:

import { useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import _ from 'lodash'

export default function useList() {
  const { data } = useQuery(GET_LIST, {
    // 可选:关闭不必要的自动重请求,避免组件重渲染时触发重复请求
    refetchOnWindowFocus: false,
    refetchOnMount: false,
  })
  
  const list = useMemo(() => {
    // 如果data不会被直接修改,可移除_.cloneDeep提升性能
    return _.cloneDeep(data)?.menuTree?.filter(i => i.parentId === null) || []
  }, [data])

  const otherMenus = useMemo(() => {
    return data?.menuTree || []
  }, [data])

  return { list, otherMenus }
}

2. 隔离输入框的重渲染范围

把输入框封装成用memo包裹的独立组件,这样只有当searchValue变化时,该组件才会重渲染,不会影响到使用useList的部分:

import { memo, useState } from 'react'
import { Input } from 'antd'

const SearchInput = memo(({ value, onChange }) => {
  return (
    <Input
      value={value}
      className="shadow-none"
      onChange={e => onChange(e.target.value)}
    />
  )
})

// 父组件中使用
const ParentComponent = () => {
  const [searchValue, setSearchValue] = useState('')
  const { list } = useList()

  return (
    <div>
      <SearchInput value={searchValue} onChange={setSearchValue} />
      {/* 渲染list相关内容 */}
    </div>
  )
}

3. 移除不必要的深拷贝

如果useQuery返回的data是只读状态(不会在组件内被修改),可以直接去掉_.cloneDeep,直接对data.menuTree做过滤——深拷贝是耗时操作,能省则省:

const list = useMemo(() => {
  return data?.menuTree?.filter(i => i.parentId === null) || []
}, [data])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:42:30