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

为何我的React组件中useEffect会触发无限循环?

React useEffect 无限循环问题解决:点击切换状态时更新数组

问题根源

你第三个useEffect的语法写错了!依赖数组[picked]被放在了useEffect的括号外面,导致这个Effect没有依赖列表——React会把没有依赖数组的Effect当成每次组件渲染都要执行的逻辑。每次执行它都会调用setImages,触发组件重新渲染,接着又执行这个Effect,无限循环就这么来了。

另外还有两个潜在问题:

  • 第二个和第三个Effect都在修改images状态,当dogs更新时会覆盖picked切换后的images值,逻辑会冲突
  • 初始dogs是空数组,直接取dogs[0]/dogs[1]/dogs[2]会导致数组越界报错

修复方案

1. 修正Effect语法错误

把第三个Effect的依赖数组放进正确的位置,同时加上dogs作为依赖(因为用到了它),还要判断数组长度避免报错:

useEffect(() => {
  if (dogs.length >= 3) {
    setImages([dogs[1], dogs[2]]);
  }
}, [picked, dogs]);

2. 统一状态更新逻辑,避免冲突

调整逻辑,让dogs加载完成后初始化images,点击切换picked时再更新images,同时处理加载中的状态:

修改后的完整Game组件代码:

import GameCSS from './game.module.css'
import Dog from "./dog/dog"
import { useState, useEffect } from 'react'

function Game () {
  const [dogs, setDogs] = useState<string[]>([]);
  const [picked, setPicked] = useState<boolean>(false);
  const [fave, setFave] = useState<string>('');
  const [images, setImages] = useState<string[]>();

  useEffect(() => {
    fetch('https://dog.ceo/api/breeds/image/random/10')
      .then(response => response.json())
      .then(data => setDogs(data.message));
  }, []);

  // 初始化images:dogs加载完成后设置初始图片
  useEffect(() => {
    if (dogs.length >= 2) {
      setImages([dogs[0], dogs[1]]);
    }
  }, [dogs]);

  // 当picked切换时更新images
  useEffect(() => {
    if (dogs.length >= 3) {
      // 可根据picked状态灵活切换图片组,这里按你的需求实现
      setImages(picked ? [dogs[1], dogs[2]] : [dogs[0], dogs[1]]);
    }
  }, [picked, dogs]);

  // 处理未加载完成的情况
  if (!images) {
    return <div>Loading...</div>
  }

  return (
    <>
      <div className={GameCSS.dogs}>
        <Dog
          image={images[0]}
          setFave={setFave}
          picked={picked}
          setPicked={setPicked}
        />
        <Dog
          image={images[1]}
          setFave={setFave}
          picked={picked}
          setPicked={setPicked}
        />
      </div>  
    </>
  )
}

export default Game

3. 额外优化

如果担心重复渲染,可以在更新images前加判断,比如对比当前值和要设置的值是否一致,不过上面的写法已经通过依赖数组控制了触发时机,基本够用。

验证效果

现在点击图片时,picked状态切换,第三个Effect会触发并更新images数组,组件重新渲染展示新的图片组合,不会再出现无限循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:17:40