首页 文章

使用render方法内的promises渲染React组件

提问于
浏览
50

我有一个组件,它将一个项目集合作为道具,并将它们作为一个组件集合,这些组件呈现为父组件的子组件 . 我们使用 WebSQL 中存储的图像作为字节数组 . 在 map 函数中,我从项目中获取图像Id,并对 DAL 进行异步调用,以获取图像的字节数组 . 我的问题是我无法将这个承诺传播到React,因为它不是为了处理渲染中的promise而设计的(不管怎样我都不知道) . 我来自 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 已经存在,我无法弄清楚我能在哪里做到这一点 .

2 回答

  • 13

    render() 方法应该从this.props和this.state呈现UI,因此要异步加载数据,可以使用 this.state 来存储 imageId:imageUrl 映射 .
    然后在 componentDidMount() 方法中,您可以从imageId填充imageUrl . 然后通过渲染 this.state 对象, render() 方法应该是纯粹而简单的

    这是一个快速示例代码:
    请注意 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>
        );
    }
    
  • 74

    或者你可以使用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}/>} />    
        );
    });
    

    完整文档:https://github.com/capaj/react-promise

相关问题