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

ReactJS实现API返回数组单个元素的弹窗展示

问题原因与解决方案

你遇到的问题核心是用了一个全局布尔状态open控制所有弹窗,只要这个状态变为true,所有循环生成的元素都会显示弹窗。要实现点击单个元素只显示对应弹窗,需要用状态记录当前激活元素的唯一标识,而非单纯的布尔值。

修改步骤

  1. 将open状态从布尔值改为记录当前激活元素的唯一标识(比如元素索引index,或Agent的唯一ID),初始值设为null。
  2. 点击Agent元素时,把状态设置为当前元素的标识。
  3. 弹窗显示条件改为:当前元素的标识与状态中的标识一致。
  4. 关闭弹窗时,将状态重置为null。

修改后的完整代码

import React, { useState, useEffect, useCallback } from 'react'
import axios from 'axios';
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';

function Agents() {
    const [responseData, setResponseData] = useState([]);
    const [doneLoading, setdoneLoading] = useState(false);
    // 改为记录当前激活的Agent索引,初始为null
    const [activeAgentIndex, setActiveAgentIndex] = useState(null);
  
    const closePopup = () => setActiveAgentIndex(null);
  
    const fetchData = useCallback(() => {
        axios({
          method: 'GET',
          url: 'https://valorant-api.com/v1/agents',
          params: { language: 'en-US', isPlayableCharacter: true }
        })
        .then((response) => {
          setResponseData(response.data.data.map(m => ({
            a: m.displayName, 
            b: m.mapUrl, 
            c: m.displayIcon,
            id: m.uuid // 用API返回的唯一ID作为标识,比索引更可靠
          })))
          setdoneLoading(true)
        })
        .catch((error) => {
          console.log(error)
        })
      }, []
    )
  
    useEffect(() => {
      fetchData()
    }, [fetchData])
  
    return (
        <div>
            <h1 className="text-3xl text-white text-center p-4">Valorant Agents</h1>
            <h2 className="text-xl text-white text-center">Click on an agent to learn more</h2>
            <div className="bg-slate-500 grid grid-cols-5 gap-4 max-h-screen">
                {doneLoading ? 
                responseData.map((agent, index) => {
                return (
                    <div key={agent.id} className="">
                        <div 
                            className="flex-col justify-center items-center p-2 border bg-slate-500 rounded-xl hover:bg-slate-700 cursor-pointer" 
                            onClick={() => setActiveAgentIndex(index)}
                        >
                          <p className="text-white text-center font-semibold">{`${index+1}. ${agent.a}`}</p>
                          <img src={agent.c} alt={agent.a} width="75px" className="mx-auto"/> 
                          <div onClick={() => setActiveAgentIndex(index)} className="text-center text-white font-semibold pt-1">Learn more</div>
                        </div>
                        {/* 仅当当前元素索引与激活索引一致时,显示弹窗 */}
                        {activeAgentIndex === index ? 
                        <>
                        <div className="text-center text-white">Returned API information would go here: {agent.a}</div>
                        <button onClick={closePopup} className="text-white border p-1 flex justify-center mx-auto">Close</button>
                        </>
                        : null}
                    </div>  
                    )
                })
                : <div className="text-white text-center col-span-5">Loading...</div>
                }
            </div>
        </div>
    );
}

export default Agents

额外优化点

  • 用Agent的唯一uuid作为元素key,比索引更可靠,避免列表更新时的渲染异常。
  • 把原生class属性替换为React推荐的className。
  • 将控制台打印的加载提示改为可视化页面提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:50:26