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

React中图片加载状态无法独立更新的问题求助

问题分析

你当前的核心问题是用**单个布尔值loaded**控制所有图片的加载状态,只要有一张图片加载完成,全局状态就会被设为true,导致其他未加载完成的图片也停止显示动画。要解决这个问题,需要为每张图片维护独立的加载状态,同时支持通过按钮批量重置所有状态。

解决方案

步骤1:修改App组件的状态管理

将单个loaded变量替换为对象类型的状态,存储每个机器人ID对应的加载状态:

import { useState, useEffect } from 'react';

function App() {
  // 其他原有状态(如robotType、filteredRobots等保持不变)
  const [robotType, setRobotType] = useState("?200x200");
  const [filteredRobots, setFilteredRobots] = useState([]);
  
  // 改为对象存储每个机器人的加载状态,key为robot.id,value为布尔值
  const [loadedStates, setLoadedStates] = useState({});

  // 初始化/更新加载状态:当机器人列表变化时,重置所有状态为false
  useEffect(() => {
    const initialStates = filteredRobots.reduce((acc, robot) => {
      acc[robot.id] = false;
      return acc;
    }, {});
    setLoadedStates(initialStates);
  }, [filteredRobots]);

  // 更新单个图片的加载状态
  const onImageLoaded = (robotId) => {
    setLoadedStates(prev => ({
      ...prev,
      [robotId]: true
    }));
  };

  // 重置所有图片的加载状态
  const resetImgState = () => {
    const resetStates = Object.keys(loadedStates).reduce((acc, id) => {
      acc[id] = false;
      return acc;
    }, {});
    setLoadedStates(resetStates);
  };

  // 原有changeSrcUrl函数保持不变
  const changeSrcUrl = (e) => {
    e.target.id === "robot" ? setRobotType("?200x200") 
        : e.target.id === "kittens" ? setRobotType("?set=set4") 
        : e.target.id === "monster" ? setRobotType("?set=set2")
        : e.target.id === "avatar" ? setRobotType("?set=set5")  
        : setRobotType("?set=set3")    
  };

  return (
    <div className="tc">
      <h1 className="f1">Fola's RoboFriends</h1>
      <SearchBox searchChange={onSearchChange}/>
      <ButtonList onClick={(e) => {
          resetImgState()
          changeSrcUrl(e)
      }}/>
      <Scroll>
        {/* 修改CardList的props传递 */}
        <CardList 
          robots={filteredRobots} 
          changeType={robotType} 
          onImageLoaded={onImageLoaded}
          loadedStates={loadedStates}
        />
      </Scroll>
    </div>
  );
}

步骤2:修改CardList组件

传递单张图片的加载状态和更新函数:

const CardList = ({ robots, changeType, onImageLoaded, loadedStates }) => {
  return (
    <>
      {robots.map((robot) => (
        <Card 
          key={robot.id} 
          id={robot.id} 
          name={robot.name} 
          email={robot.email} 
          img={changeType}
          onImageLoaded={onImageLoaded}
          isLoaded={loadedStates[robot.id]}
        />
      ))}
    </>
  );
}

步骤3:修改Card组件

透传单个图片的状态和更新函数:

const Card = ({ name, email, id, img, onImageLoaded, isLoaded }) => {
  return (
    <div className="tc hover-bg-light-purple bg-light-blue dib br3 pa3 ma2 grow bw2 shadow-5">  
       <Image 
         id={id} 
         img={img} 
         onImageLoaded={onImageLoaded}
         isLoaded={isLoaded}
       />
        <div>
          <h2>{name}</h2>
          <p>{email}</p>
        </div>
    </div>
  );
}

步骤4:修改Image组件

根据当前图片的独立状态控制动画显示,并在加载完成时更新对应ID的状态:

const Image = ({id, img, onImageLoaded, isLoaded}) => {
  return (
    <>
      <img 
        alt=""
        src={`https://robohash.org/blteuwoqqqe${id}${img}`} 
        onLoad={() => onImageLoaded(id)}
        id={id}
      />
      {/* 仅当前图片未加载完成时显示动画 */}
      {!isLoaded && (
        <div className="bg-light-blue container-overlay">
          <div className="tc" id="loading"></div>
        </div>
      )} 
    </>
  )
}

export default Image;
核心逻辑说明
  1. 独立状态存储:用对象loadedStates记录每个机器人图片的加载状态,避免全局状态干扰。
  2. 批量重置:点击按钮时,遍历对象将所有ID对应的状态设为false,实现全量重置。
  3. 精准更新:每张图片加载完成时,仅更新自身ID对应的状态,不影响其他图片的动画显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:53:21