ReactJS实现API返回数组单个元素的弹窗展示
问题原因与解决方案
你遇到的问题核心是用了一个全局布尔状态open控制所有弹窗,只要这个状态变为true,所有循环生成的元素都会显示弹窗。要实现点击单个元素只显示对应弹窗,需要用状态记录当前激活元素的唯一标识,而非单纯的布尔值。
修改步骤
- 将
open状态从布尔值改为记录当前激活元素的唯一标识(比如元素索引index,或Agent的唯一ID),初始值设为null。 - 点击Agent元素时,把状态设置为当前元素的标识。
- 弹窗显示条件改为:当前元素的标识与状态中的标识一致。
- 关闭弹窗时,将状态重置为
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
相关产品推荐
相关产品推荐

