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

React中useEffect设空依赖数组调用setState仍触发无限循环如何解决?

问题根因

你的无限循环问题和useEffect无关,是button的事件绑定写法错误导致的:

  • 你给onClick直接赋值了onToggleArchived(callInfo.id),这会在组件每次渲染时立即执行这个函数,而不是等到用户点击按钮时才触发。如果onToggleArchived内部会修改父组件的状态,就会触发父组件重渲染,进而让当前的ActivityDetail组件跟着重渲染,重渲染时又会再次执行onToggleArchived,形成死循环。
  • 另外你的useEffect写法存在不规范问题:依赖数组为空但用到了外部的call变量,后续如果call的值更新,callInfo不会同步更新,也会触发Hook依赖检查警告。实际上你完全不需要单独维护callInfo这个冗余状态,直接使用路由拿到的call即可。
修复后代码
import { useLocation } from "react-router-dom";

const ActivityDetail = ({ onToggleArchived }) => {
  const { call } = useLocation().state;

  return (
    <div>
      <h3 className="title">通话详情</h3>
      <hr />
      {call && <div>
          <p>来电方: {call.from}</p>
          <p>接听方: {call.to}</p>
          <p>通话时间: {call.created_at}</p>
          {/* 用箭头函数包裹,点击时才执行逻辑 */}
          <button onClick={() => onToggleArchived(call.id)}>
            {call.is_archived ? "取消归档" : "归档"}
          </button>
        </div>
      }
    </div>
  )
}

export default ActivityDetail
改动说明
  • 删除了冗余的callInfo状态和对应的useEffect,直接使用路由拿到的call数据,减少不必要的状态更新。
  • 把onClick的绑定改为箭头函数包裹onToggleArchived调用,确保只有用户点击按钮时才会执行该函数,避免渲染时自动触发。

如果你确实需要单独维护callInfo状态,只需要做两处修改即可:

  1. 把call加入useEffect的依赖数组:useEffect(() => { setCallInfo({ ...call }); }, [call])
  2. 修正onClick的绑定写法为箭头函数包裹。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:09:02