React中如何避免搜索输入变化时因依赖更新触发useEffect执行?
解决搜索输入时
validateUser重复执行的问题 问题根源
每次在搜索框输入内容时,searchValue变化会触发组件重渲染,而你的useList钩子中,list是每次渲染都通过_.cloneDeep和filter生成的新数组(引用地址不同),导致useEffect的依赖list每次都变化,进而重复执行validateUser。另外你的列表过滤逻辑存在依赖缺失问题,搜索输入后列表不会正确更新,这个也顺便修正。
具体解决方案
1. 缓存useList中的list,避免不必要的引用变化
修改useList钩子,用useMemo缓存list和otherMenus,只有当接口返回的data变化时才重新生成:
export default function useMenu() { const { data } = useQuery(GET_LIST) const list = useMemo(() => { return _.cloneDeep(data)?.menuTree?.filter((i) => i.parentId === null) || [] }, [data]) const otherMenus = useMemo(() => { return data?.menuTree || [] }, [data]) return { list, otherMenus } }
这样搜索输入时,data没有变化,list的引用就会保持稳定,不会触发useEffect的重复执行。
2. 修正列表过滤的依赖问题(可选但必要)
当前的allLists依赖中缺少searchValue,导致搜索输入后列表不会更新。需要把searchValue作为参数传入过滤函数,并添加到useMemo依赖中:
const getFilteredElements = (items, searchValue) => { let parentMatched = false const filteredItems = items.filter((item) => { if (item.title.toLowerCase().includes(searchValue.toLowerCase())) { parentMatched = true return true } return false }) return { filteredItems, parentMatched } } const createListBasedOnUser = (items, searchValue, filterChildren = false) => { const { filteredItems, parentMatched } = getFilteredElements(items, searchValue) const result = [] for (const item of filterChildren ? items : filteredItems) { result.push({ title: item.title, }) } return result // 原代码未返回结果,此处补充 } const allLists = useMemo(() => { const elements = createListBasedOnUser(list, searchValue, false) return elements ? [...elements] : [] }, [list, collapsed, searchValue]) // 添加searchValue到依赖
3. 确保validateUser函数稳定(如果是组件内定义)
如果validateUser是在当前组件内部定义的函数,每次组件重渲染它都会生成新的引用,也可能间接导致问题,需要用useCallback缓存:
const validateUser = useCallback((currentUser, list) => { // 你的validateUser逻辑 }, []) // 此处添加函数内部用到的外部依赖变量
内容的提问来源于stack exchange,提问作者Mir Stephen
相关产品推荐
相关产品推荐

