React中如何避免useEffect无限循环同时实现状态变更即时响应
问题根因
你遇到的无限循环问题来自两个错误的实现逻辑:
- 组件每次重渲染都会生成新的
handleClick函数实例,将它作为useEffect的依赖时,每次渲染都会触发useEffect执行,而useEffect内部调用setDisplayWork会再次触发渲染,最终形成死循环 - 你额外维护了
displayWork状态,完全可以基于已有的category和workList状态派生,不需要单独做状态同步,反而容易引发更新不同步的问题
最优实现方案
直接删除displayWork相关状态和冗余的handleClick、useEffect逻辑,直接基于分类派生过滤结果即可:
import { useState } from 'react'; const WorkPage = () => { // 仅保留两个必要状态:全量工作列表、当前选中分类 const [workList, setWorkList] = useState([ { title: "aaa", image: "./images/1.jfif", type: "landscaping" }, { title: "plumbing", image: "./images/2.jfif", type: "plumbing" }, { title: "Other 3", image: "./images/3.png", type: "other3" }, { title: "Other 4", image: "./images/3.png", type: "other4" }, ]); // 可设置默认展示的分类 const [category, setCategory] = useState("landscaping"); // 直接基于当前分类过滤出要展示的内容 const displayWork = workList.filter(work => work.type === category); return ( <> {/* 分类选择区,点击直接修改分类状态即可 */} <div className="row"> <div className="col-sm-2 workCatagory" onClick={() => setCategory("landscaping")}> Land Scaping </div> <div className="col-sm-2 workCatagory" onClick={() => setCategory("plumbing")}> plumbing </div> <div className="col-sm-2 workCatagory" onClick={() => setCategory("other3")}> test3 </div> <div className="col-sm-2 workCatagory" onClick={() => setCategory("other4")}> Test4 </div> </div> {/* 渲染过滤后的内容 */} <div className="work-list"> {displayWork.map(item => ( <div key={item.title} className="work-item"> <img src={item.image} alt={item.title} /> <p>{item.title}</p> </div> ))} </div> </> ) }
如果你的workList数据量较大(超过100条),可以用useMemo缓存过滤结果避免不必要的重复计算:
import { useState, useMemo } from 'react'; // ...其他逻辑不变 const displayWork = useMemo(() => { return workList.filter(work => work.type === category); }, [workList, category]); // 仅当工作列表或选中分类变化时才重新过滤
原有写法的修复方案
如果一定要保留displayWork状态,修改useEffect的依赖项即可解决无限循环问题:
// 删除原来的handleClick和依赖handleClick的useEffect useEffect(() => { const filteredWork = workList.filter(work => work.type === category); setDisplayWork(filteredWork); }, [category, workList]); // 仅当分类或全量列表变化时才更新展示列表
内容的提问来源于stack exchange,提问作者Dylan Bozarth
相关产品推荐
相关产品推荐

