在 render 方法中使用 promise 渲染 React 组件
Rendering React components with promises inside the render method
我有一个组件,它获取项目集合作为道具,并将它们 map
发送到组件集合中,这些组件呈现为父组件的子组件。我们使用存储在 WebSQL
中的图像作为字节数组。在 map
函数中,我从项目中获取图像 ID,并异步调用 DAL
以获得图像的字节数组。我的问题是我无法将 promise 传播到 React,因为它不是为处理渲染中的 promises 而设计的(至少据我所知)。我来自 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,但随后出现错误,因为我的渲染函数 return 是一个 promise 而不是合法的 JSX。我在想,也许我需要利用 React
生命周期方法之一来获取数据,但由于我需要 props
已经存在,所以我不知道在哪里可以这样做。
render()
方法应该从 this.props
和 this.state
渲染 UI,所以要异步加载数据,可以使用 this.state
来存储 imageId: imageUrl
映射。
然后在您的 componentDidMount()
方法中,您可以从 imageId
填充 imageUrl
。然后 render()
方法应该通过渲染 this.state
对象
来简单明了
请注意,this.state.imageUrls
是异步填充的,因此呈现的图像列表项将在其 url 被获取后一个接一个地出现。您还可以使用所有图像 ID 或索引(没有 urls)初始化 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>
);
}
或者你可以使用 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}/>} />
);
});
编辑:2019 年 10 月
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>}
}
完整文档:react-promise
我有一个组件,它获取项目集合作为道具,并将它们 map
发送到组件集合中,这些组件呈现为父组件的子组件。我们使用存储在 WebSQL
中的图像作为字节数组。在 map
函数中,我从项目中获取图像 ID,并异步调用 DAL
以获得图像的字节数组。我的问题是我无法将 promise 传播到 React,因为它不是为处理渲染中的 promises 而设计的(至少据我所知)。我来自 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,但随后出现错误,因为我的渲染函数 return 是一个 promise 而不是合法的 JSX。我在想,也许我需要利用 React
生命周期方法之一来获取数据,但由于我需要 props
已经存在,所以我不知道在哪里可以这样做。
render()
方法应该从 this.props
和 this.state
渲染 UI,所以要异步加载数据,可以使用 this.state
来存储 imageId: imageUrl
映射。
然后在您的 componentDidMount()
方法中,您可以从 imageId
填充 imageUrl
。然后 render()
方法应该通过渲染 this.state
对象
请注意,this.state.imageUrls
是异步填充的,因此呈现的图像列表项将在其 url 被获取后一个接一个地出现。您还可以使用所有图像 ID 或索引(没有 urls)初始化 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>
);
}
或者你可以使用 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}/>} />
);
});
编辑:2019 年 10 月
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>}
}
完整文档:react-promise