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> ); } } }
问题根源
- 全局变量污染:
img变量未声明,默认成为全局变量。多个Dialog并行请求图片时,最后完成的请求会覆盖全局img的值,导致所有组件都拿到最后一张图的Base64。 - 异步逻辑错误:
getImage是异步操作,但直接返回img,此时img还未被赋值;后续异步回调修改img时,因为没有用state管理,React无法感知变化,不会触发组件重新渲染。 - 状态管理不规范:用
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
相关产品推荐
相关产品推荐

