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

React前端请求后端接口获取对应ID图片并渲染的解决方案求助

问题解决方案

原代码存在的核心问题

  • 状态更新异步问题:setItineraries是异步操作,执行完后立即遍历itineraries数组时,拿到的还是初始空数组,不会实际触发图片请求
  • 状态更新不符合React规范:直接对itineraryImage/itineraryCovImage执行push操作,没有调用对应的set方法,React无法感知状态变化,不会触发重渲染
  • 关联关系错乱:异步请求的返回顺序不可控,直接按返回顺序push到数组,无法保证图片和对应的行程一一对应
  • 冗余请求:后端图片接口本身支持直接访问,不需要用axios拉取图片数据再存储,属于多余操作

最优解决方案(无需额外请求)

你的后端图片接口可以直接作为img标签的src属性值使用,完全不需要额外发axios请求存储图片数据,修改逻辑如下:

  1. 删掉itineraryImage、itineraryCovImage两个状态,以及useEffect里所有的图片axios请求逻辑
  2. 渲染CardImg时直接拼接接口地址作为src
  3. 点击查看行程时,把当前行程的id传入,用于拼接另一张图片的地址传递给组件

修改后的前端代码示例

import {Card , CardImg , CardBody , CardTitle , CardText , Button } from 'reactstrap';
import {useState} from 'react';
import { useEffect } from 'react';
import ItineraryContainer from 'components/ItineraryContainer';
import Backdrop from 'components/ItineraryBackdrop';
import styles from '../assets/css/Itinerary.module.css'
import axios from 'axios';
        
function Itineraries(){
    const [itineraries , setItineraries] = useState([]);
    const [currentItinerary, setCurrentItinerary] = useState(null); // 存储当前点击的行程
    const [ItineraryisOpen , setItineraryOpen] = useState(false);

    useEffect(() =>{
        axios.get("http://localhost:8070/itineraries/").then((res)=>{
            setItineraries(res.data);
        }).catch((err)=>{
            console.log(err);
        })
    } , []);

    function ViewItinerary(itinerary){
        setCurrentItinerary(itinerary);
        setItineraryOpen(true);
    }

    function ItineraryisClosed(){
        setItineraryOpen(false);
        setCurrentItinerary(null);
    }

    return(
        <div>   
            <div className = {styles.Packages}>
                <h3>Our Tours</h3>
                <br/><br/>
                <div className = {styles.container} >
                {itineraries.map((itinerary) =>(
                    <Card key={itinerary._id} style = {{width: '20rem' , margin : '50px'}}>
                    {/* 直接拼接封面图接口地址作为src */}
                    <CardImg  top src={`http://localhost:8070/itineraries/getCovImage/${itinerary._id}`} alt = "TourImage" />
                    <CardBody>
                        <CardTitle>{itinerary.itineraryName}</CardTitle>
                        <CardText>
                        {itinerary.itineraryDesc}<br/><br/>
                            <b>Itinerary Days  : {itinerary.itineraryDays} </b>
                            <b>Itinerary Class : {itinerary.itineraryClass}</b>
                            <b>Price Per Adult : {itinerary.itineraryPriceAdult}  </b> <br/>
                            <b>Price per Child : {itinerary.itineraryPriceChild} </b>
                        </CardText>
                        {/* 点击时传入当前行程 */}
                        <Button color = "primary" onClick = {() => ViewItinerary(itinerary)} >View Itinerary</Button>
                        <Button color = "info" style = {{float : 'right'}}>Book Tour</Button>
                    </CardBody>        
                    </Card>
                ))}
                </div>
                {/* 把行程的另一张图片地址作为prop传递 */}
                {ItineraryisOpen && currentItinerary ? 
                  <ItineraryContainer 
                    onCancel = {ItineraryisClosed}
                    itineraryImage={`http://localhost:8070/itineraries/getImage/${currentItinerary._id}`}
                  /> : null}
                {ItineraryisOpen && <Backdrop onCancel = {ItineraryisClosed}/>}
            </div>
        </div>
    );
}

export default Itineraries;

特殊场景方案(需要预加载图片到本地)

如果业务需要提前把图片数据加载到前端存储,可以用对象存储图片,key为行程id保证关联正确:

// 状态修改为对象类型
const [imageMap, setImageMap] = useState({});

// useEffect里获取图片的逻辑
useEffect(() =>{
  axios.get("http://localhost:8070/itineraries/").then(async (res) =>{
    setItineraries(res.data);
    const tempMap = {};
    // 等待所有图片请求完成
    await Promise.all(res.data.map(async (i) => {
      const [imgRes, covRes] = await Promise.all([
        axios.get(`http://localhost:8070/itineraries/getImage/${i._id}`, {responseType: 'blob'}),
        axios.get(`http://localhost:8070/itineraries/getCovImage/${i._id}`, {responseType: 'blob'})
      ]);
      // 转成本地可访问的url
      tempMap[i._id] = {
        itineraryImage: URL.createObjectURL(imgRes.data),
        coverImage: URL.createObjectURL(covRes.data)
      }
    }))
    setImageMap(tempMap);
  }).catch((err)=>{
    console.log(err);
  })
}, []);

// 渲染时读取
<CardImg top src={imageMap[itinerary._id]?.coverImage || '默认图地址'} alt="TourImage" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:54:02