React useEffect未声明search依赖却随输入意外执行排查
问题原因
你遇到的useEffect非预期触发,核心是两个逻辑错误:
- 把需要手动点击触发的搜索请求
getProducts写在了依赖驱动的useEffect里,只要useEffect的依赖项(products、limitPage、page)任意一个发生变化,哪怕变化和search无关,都会重新执行整个副作用函数,包含里面的请求逻辑。输入内容时setSearch会触发组件重渲染,开发环境如果开启了React严格模式,会额外执行一次渲染+副作用校验,很容易出现你观察到的「输入就触发请求」的现象。 handleSearch里的状态更新写法有问题:setLimitPage、setPage是异步操作,你调用后立刻读取limitPage、page拿到的还是旧值,本身就会导致请求参数错误。
另外你的输入框旁的按钮标签存在语法错误,起始标签没有闭合,也可能导致渲染行为异常。
修复方案
核心思路是把请求触发逻辑和请求结果后处理逻辑完全拆分:搜索请求只在点击按钮的handleSearch里执行,useEffect只负责拿到接口返回的products数据后,做分页相关的状态计算,不在useEffect里发起任何请求。
1. 修正搜索触发函数
不要依赖setState的异步结果传参,点击搜索时直接用确定的分页参数发请求,再同步更新本地状态:
const handleSearch = async () => { // 搜索时固定重置为第一页、每页10条,直接用确定值传参 const fixedLimit = 10 const fixedPage = 1 // 同步更新本地分页状态 setLimitPage(fixedLimit) setPage(fixedPage) // 直接传入确定的参数发起请求,避免拿到旧状态值 await getProducts(fixedLimit, fixedPage, search) }
同时修正按钮的语法错误,补全起始标签的闭合尖括号:
<div className="flex gap-1"> <input className="border-1 border-2 border-solid rounded border-slate-300" value={search} onChange={(e) => setSearch(e.target.value)} /> <button onClick={() => handleSearch()}> <FiSearch/> </button> </div>
2. 修正useEffect逻辑
删除useEffect里的getProducts调用,这个副作用只在products数据返回后做分页状态计算:
useEffect (() => { // 仅做接口返回结果的后处理,不在这里触发任何请求 const totalDocsVal = products.products?.totalDocs ?? 0 setTotalDocs(totalDocsVal) setTotalPages(products.products?.totalPages ?? 0) setCurrentPage(products.products?.page ?? 1) setNextPage(products.products?.hasNextPage ?? false) setPreviousPage(products.products?.hasPrevPage ?? false) const totalPages = Math.ceil(totalDocsVal/limitPage) const links = [] for (let i = 1; i <= totalPages; i++) { // 原写法links[i] = i会导致数组第0位为空,用push更合理 links.push(i) } setNumbers(links) // 仅保留后处理逻辑需要的依赖,page状态不需要放在这里,翻页触发的请求也应该由翻页事件手动调用getProducts }, [products, limitPage])
可选优化
如果需要支持回车触发搜索,可以给input加onKeyDown事件,判断按下回车时调用handleSearch即可;如果需要避免输入过程中频繁setSearch触发重渲染,可以给input加300ms左右的防抖,不影响核心逻辑。
内容的提问来源于stack exchange,提问作者OscarDev
相关产品推荐
相关产品推荐

