我有一个组件,它将一个项集合作为props,map
将它们作为一个组件集合,这些组件呈现为父组件的子组件。我们使用WebSQL
中存储的图像作为字节数组。在map
函数中,我从项中获取图像ID,并对DAL
进行异步调用,以获取图像的字节数组。我的问题是我无法将承诺传播到React,因为它不是为了处理渲染中的承诺而设计的(不管怎样我都不知道)。我来自C#
背景,所以我想我正在寻找类似于await
关键字的重新同步分支代码。
map
函数看起来像这样(简化):
var items = this.props.items.map(function (item) {
var imageSrc = Utils.getImageUrlById(item.get('ImageId')); // <-- this contains an async call
return (
<MenuItem text={item.get('ItemTitle')}
imageUrl={imageSrc} />
);
});
并且getImageUrlById
方法如下所示:
getImageUrlById(imageId) {
return ImageStore.getImageById(imageId).then(function (imageObject) { //<-- getImageById returns a promise
var completeUrl = getLocalImageUrl(imageObject.StandardConImage);
return completeUrl;
});
}
这不起作用,但我不知道我需要修改什么来使这项工作。我尝试向链添加另一个promise,但后来我得到一个错误,因为我的render函数返回一个promise而不是合法的JSX。我在想,也许我需要利用其中一个React
生命周期方法来获取数据,但由于我需要props
已经存在,我无法弄清楚我能在哪里找到这样做。
答案 0 :(得分:77)
render()
方法应该从this.props和this.state呈现UI,因此对于异步加载数据,您可以使用this.state
来存储imageId:imageUrl
映射。
然后在componentDidMount()
方法中,您可以从imageId填充imageUrl。然后,通过呈现render()
对象
this.state
方法应该是纯粹而简单的
以下是一个快速示例代码:
请注意,this.state.imageUrls
是异步填充的,因此渲染的图像列表项将在获取其URL后逐个显示。您还可以使用所有图像ID或索引(不带网址)初始化this.state.imageUrls
,这样您就可以在加载图像时显示加载程序。
constructor(props) {
super(props)
this.state = {
imageUrls: []
};
}
componentDidMount() {
var self = this;
this.props.items.map((item) => {
ImageStore.getImageById(item.imageId).then(image => {
var mapping = {id: item.imageId, url: image.url};
var newUrls = self.state.imageUrls.slice();
newUrls.push(mapping);
self.setState({
imageUrls: newUrls
});
})
});
}
render() {
return (<div>
this.state.imageUrls.forEach(mapping => {
<div>id: {mapping.id}, url: {mapping.url}`</div>
})
</div>
);
}
答案 1 :(得分:16)
或者您可以使用react-promise:
安装包:
npm i react-promise
你的代码看起来像这样:
import Async from 'react-promise'
var items = this.props.items.map(function (item) {
var imageSrc = Utils.getImageUrlById(item.get('ImageId')); // <-- this contains an async call
return (
<Async promise={imageSrc} then={(val) => <MenuItem text={item.get('ItemTitle')} imageUrl={val}/>} />
);
});