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

React中Promise.all+map结合useState触发无限循环问题求助

问题根源

你的代码触发无限循环的核心原因是**useEffect没有设置依赖数组**:

  • 组件每次渲染(包括调用setArtistInfo更新state导致的重渲染)都会执行useEffect里的getArtistInformation。
  • 而getArtistInformation里的setArtistInfo又会触发组件重渲染,形成无限循环。

另外还有两个潜在问题需要一并修复:

  1. getThisArtistInfo在artistInfo为空或找不到匹配项时,会因为访问undefined.data抛出错误。
  2. 每次组件渲染都会新建SpotifyApi实例,造成不必要的资源浪费。
解决方案

1. 给useEffect添加正确的依赖数组

只在spotifyArtistIds发生变化时才调用getArtistInformation,避免无意义的重复执行:

useEffect(() => {
  getArtistInformation()
}, [spotifyArtistIds]) // 依赖数组:仅当spotifyArtistIds变化时触发

2. 优化getThisArtistInfo的空值处理

避免数组为空或无匹配项时的报错:

const getThisArtistInfo = () => {
  const matchedArtist = artistInfo.find(info => info.data.id === showId)
  return matchedArtist?.data
}

(用find替代filter更高效,因为只需要找到第一个匹配项)

3. 缓存SpotifyApi实例

把实例化提到组件外部,全局只创建一次,避免每次渲染新建:

// 提到组件外,全局仅实例化一次
const spotiApi = new SpotifyApi();

export const DashboardView = () => {
  // ... 其他代码
}
修改后的完整代码
import { Box } from "@mui/material";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import SpotifyApi from "../../api/SpotifyApi";

// 全局实例化一次SpotifyApi
const spotiApi = new SpotifyApi();

export const DashboardView = () => {
  const spotifyArtistIds = useSelector(state => state.member.spotifyArtistIds)

  const [artistInfo, setArtistInfo] = useState([])
  // 处理spotifyArtistIds为空的情况,避免showId初始值为undefined
  const [showId, setShowId] = useState(spotifyArtistIds[0] || '')

  const getArtistInformation = () => {
    // 空数组时直接返回,避免不必要的API调用
    if (!spotifyArtistIds.length) return;
    
    console.log("sp ids", spotifyArtistIds)
    Promise.all(spotifyArtistIds.map(id => spotiApi.getArtistInfo(id)))
      .then(respList => {
        setArtistInfo(respList)
        // state更新是异步的,直接打印respList更准确
        console.log("artistInfo", respList)
      })
      // 添加错误捕获,避免API调用失败导致组件崩溃
      .catch(err => {
        console.error("获取艺术家信息失败", err)
      })
  }

  const getThisArtistInfo = () => {
    const matchedArtist = artistInfo.find(info => info.data.id === showId)
    return matchedArtist?.data
  }
  
  useEffect(() => {
    getArtistInformation()
  }, [spotifyArtistIds]) // 仅当spotifyArtistIds变化时触发

  return (
    <Box>
      <h2>{getThisArtistInfo()?.name || 'Unknown Artist'}'s Dashboard</h2>
    </Box>
  )
}

额外说明:

  • React的state更新是异步操作,调用setArtistInfo后artistInfo不会立即更新,所以打印返回的respList更准确。
  • 增加了空数组判断和错误捕获,提升组件的健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:38:14