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

React组件渲染重复图片:Base64获取正常但显示一致

React渲染Base64图片时所有图片显示相同的问题

问题场景

服务器以Base64格式存储用户图片,在React中获取并渲染时,所有图片显示为同一张。相关实现代码如下:

Viewer组件(渲染多个Dialog)

class Viewer extends Component {
      render() {
        return (
          <View>
            <Dialog name={'0'} id={'0'}/>
            <Dialog name={'54353'} id={'54353'}/>
            <Dialog name={'54354'} id={'54354'}/>
          </View>
        );
      }
}

Dialog组件的图片获取逻辑

componentDidMount(){
    this.img = this.getImage(this.name);
}

getImage(_id) {
        const fileBlob = new FileReader();
        fetch(domenName + '/server/getUserImageById.php?user_id=' + _id)
          .then(response => response.blob())
          .then(response => {
              this.loading = false;
              this.setState({loading: false});
              response.size == 0 ? img = domenName + '/assets/img/noimage.png':
                [fileBlob.readAsDataURL(response), fileBlob.onload = () => {
                  img = fileBlob.result;
                }]
          }).catch(error => {
            this.loading = false;
          })
        return img;
}

Dialog组件的渲染逻辑

class Dialog extends Component {
      render(){
        if(this.loading){
          return (
            <View>
              <Text>Loading...</Text> 
              <Text>Im user №{this.id}!</Text> 
            </View>    
          );
        }
        else{
          return (
            <View>
              <Image 
                key = {this.id}
                source={{uri: this.img}} 
                style={{ width: 60, height: 60, borderRadius: 30 }} 
              />
              <Text>Im user №{this.id}!</Text> 
            </View>    
          );
        }
      }
}

问题根源

  1. 全局变量污染:img变量未声明,默认成为全局变量。多个Dialog并行请求图片时,最后完成的请求会覆盖全局img的值,导致所有组件都拿到最后一张图的Base64。
  2. 异步逻辑错误:getImage是异步操作,但直接返回img,此时img还未被赋值;后续异步回调修改img时,因为没有用state管理,React无法感知变化,不会触发组件重新渲染。
  3. 状态管理不规范:用this.loading、this.img这类实例属性管理状态,React无法追踪这些变化,导致渲染的是初始无效值,最终全局img被覆盖后,所有组件都显示同一张图。

修复方案

1. 用组件State管理状态

将图片数据和加载状态放入组件state,确保状态变化能触发重新渲染:

class Dialog extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      img: ''
    };
  }

2. 修正异步图片获取逻辑

在异步回调中通过setState更新状态,避免全局变量污染:

componentDidMount(){
  this.getImage(this.props.name);
}

getImage(_id) {
  fetch(domenName + '/server/getUserImageById.php?user_id=' + _id)
    .then(response => response.blob())
    .then(response => {
      if (response.size === 0) {
        this.setState({
          loading: false,
          img: domenName + '/assets/img/noimage.png'
        });
      } else {
        const fileBlob = new FileReader();
        fileBlob.onload = () => {
          this.setState({
            loading: false,
            img: fileBlob.result
          });
        };
        fileBlob.readAsDataURL(response);
      }
    }).catch(error => {
      this.setState({
        loading: false,
        img: domenName + '/assets/img/noimage.png'
      });
    });
}

3. 修正渲染逻辑,使用State中的数据

render(){
  const { loading, img } = this.state;
  const { id } = this.props;

  if(loading){
    return (
      <View>
        <Text>加载中...</Text> 
        <Text>我是用户№{id}!</Text> 
      </View>    
    );
  } else {
    return (
      <View>
        <Image 
          key={id}
          source={{uri: img}} 
          style={{ width: 60, height: 60, borderRadius: 30 }} 
        />
        <Text>我是用户№{id}!</Text> 
      </View>    
    );
  }
}

4. 正确使用Props

Dialog组件中通过this.props.name和this.props.id获取传入的属性,避免直接使用未绑定实例的this.name、this.id。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:05:34