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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 07:54:00