[英]Rendering React components with promises inside the render method
I have a component which gets a collection of items as props and map
s them to a collection of components which are rendered as children of a parent component.我有一个组件,它获取一组项目作为道具并将它们
map
到一组组件,这些组件被呈现为父组件的子组件。 We use images stored in WebSQL
as byte arrays.我们使用存储在
WebSQL
图像作为字节数组。 Within the map
function I get an image Id from the item and make an async call to the DAL
in order to get the byte array for the image.在
map
函数中,我从项目中获取图像 Id 并对DAL
进行异步调用以获取图像的字节数组。 My problem is that I cannot propagate the promise in to React, since it was not designed to deal with promises in rendering (not as far as I can tell anyway).我的问题是我无法将承诺传播到 React,因为它不是为了处理渲染中的承诺而设计的(无论如何我都不能说)。 I come from a
C#
background, so I guess I'm looking for something like the await
keyword for resync-ing branched code.我来自
C#
背景,所以我想我正在寻找类似await
关键字的东西来重新同步分支代码。
The map
function looks something like this (simplified): 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} />
);
});
and the getImageUrlById
method looks like this: getImageUrlById
方法如下所示:
getImageUrlById(imageId) {
return ImageStore.getImageById(imageId).then(function (imageObject) { //<-- getImageById returns a promise
var completeUrl = getLocalImageUrl(imageObject.StandardConImage);
return completeUrl;
});
}
This doesn't work, but I don't know what I need to modify to make this work.这不起作用,但我不知道我需要修改什么才能使其工作。 I tried adding another promise to the chain, but then I get an error because my render function return a promise instead of legal JSX.
我尝试向链中添加另一个承诺,但随后出现错误,因为我的渲染函数返回一个承诺而不是合法的 JSX。 I was thinking that maybe I need to leverage one of the
React
life-cycle methods to fetch the data, but since I need the props
to already be there, I can't figure out where I can do this.我在想,也许我需要利用
React
生命周期方法之一来获取数据,但由于我需要props
已经存在,我不知道在哪里可以做到这一点。
render()
method should render UI from this.props
and this.state
, so to asynchronously load data, you can use this.state
to store imageId: imageUrl
mapping. render()
方法应该从this.props
和this.state
渲染 UI,所以为了异步加载数据,你可以使用this.state
来存储imageId: imageUrl
映射。
Then in your componentDidMount()
method, you can populate imageUrl
from imageId
.然后在你的
componentDidMount()
方法,你可以填充imageUrl
从imageId
。 Then the render()
method should be pure and simple by rendering the this.state
object然后通过渲染
this.state
对象, render()
方法应该是纯粹而简单的
Note that the this.state.imageUrls
is populated asynchronously, so the rendered image list item will appear one by one after its url is fetched.注意
this.state.imageUrls
是异步填充的,所以渲染出来的图片列表项会在获取到 url 后一一出现。 You can also initialize the this.state.imageUrls
with all image id or index (without urls), this way you can show a loader when that image is being loaded.您还可以使用所有图像 ID 或索引(不带 url)初始化
this.state.imageUrls
,这样您就可以在加载该图像时显示加载器。
constructor(props) {
super(props)
this.state = {
imageUrls: []
};
}
componentDidMount() {
this.props.items.map((item) => {
ImageStore.getImageById(item.imageId).then(image => {
const mapping = {id: item.imageId, url: image.url};
const newUrls = this.state.imageUrls.slice();
newUrls.push(mapping);
this.setState({ imageUrls: newUrls });
})
});
}
render() {
return (
<div>
{this.state.imageUrls.map(mapping => (
<div>id: {mapping.id}, url: {mapping.url}</div>
))}
</div>
);
}
Or you can use react-promise :或者你可以使用 react-promise :
Install the package :安装软件包:
npm i react-promise
And your code will look something like so :你的代码看起来像这样:
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}/>} />
);
});
Edit: Oct 2019编辑:2019 年 10 月
The last build of react-promise provide a hook called usePromise
: react-promise 的最后一次构建提供了一个名为
usePromise
的钩子:
import usePromise from 'react-promise';
const ExampleWithAsync = (props) => {
const {value, loading} = usePromise<string>(prom)
if (loading) return null
return <div>{value}</div>}
}
Full docs: react-promise完整文档: react-promise
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.