使用Reactjs从客户端上的文件数组渲染图像

使用Reactjs从客户端上的文件数组渲染图像,reactjs,file,file-upload,Reactjs,File,File Upload,我是一个新的反应,我正在实施一个多文件上传系统。我已经通过按钮上的点击事件处理程序实现了用户驱动的文件选择,该按钮将所选文件添加到数组中 出于某种原因,每当我选择一个文件时,控制台中会显示以下错误,导致应用程序停止工作: 未捕获不变冲突:对象作为子对象无效 找到:[对象承诺]。如果要呈现一组 子级,请改用数组 作为参考,此功能的我的界面如下所示: 以下是我的组件实现的相关部分: state = { selectedPortifolio: {}, portflioFiles: [] }

我是一个新的反应,我正在实施一个多文件上传系统。我已经通过按钮上的点击事件处理程序实现了用户驱动的文件选择,该按钮将所选文件添加到数组中

出于某种原因,每当我选择一个文件时,控制台中会显示以下错误,导致应用程序停止工作:

未捕获不变冲突:对象作为子对象无效 找到:[对象承诺]。如果要呈现一组 子级,请改用数组

作为参考,此功能的我的界面如下所示:

以下是我的组件实现的相关部分:

state = {
  selectedPortifolio: {},
  portflioFiles: []
}
在文件onchange事件上调用此方法

loadPortfolio = (e) => {
        if (e.target.files) {
            this.setState({
                selectedPortifolio: {
                    file: e.target.files[0],
                    filename: e.target.files[0].name
                }
            });
        }
    };
当单击add按钮时,将调用此方法

addPortfolio = () => {
        if (
            this.state.selectedPortifolio &&
            this.state.selectedPortifolio.file
        ) {
            let items = this.state.portflioFiles;
            items.push(this.state.selectedPortifolio);
            this.setState({ selectedPortifolio: {}, portflioFiles: items });
            console.log(this.state.portflioFiles);
        }
    };
所有这些之后,我将这个数组加载到div中

{this.state.portflioFiles.length > 0 ? (
    this.state.portflioFiles.map((item, index) => {
        return (
            <div className="portfolio-file" key={index}>
                {getDataURL(item.file).then((data) => {
                    return (
                        <image
                            src={data}
                            alt={item.filename}
                        />
                    );
                })}
            </div>
        );
    })
) : (
    <div></fdv>
)}

目前,您的代码正试图通过调用getDataURL函数映射portfolioItems来直接呈现promise对象。目前,React基于同步渲染,这意味着React目前不可能实现基于承诺的渲染

为了实现您所需要的,考虑解决GETDATAURL在AdppDebug中的呈现逻辑IE之外返回的承诺。 这需要对组件状态进行扩展,以保存由getDataURL返回的承诺解析的图像数据。然后,您需要更新组件的渲染逻辑,以便从当前处于组件状态的图像数据渲染图像:

更新状态形状

更新addPortfolio

更新渲染逻辑


希望有帮助

所以我在用户单击add按钮时将文件转换为dataurl?是的,这是正确的,您希望将promise/async代码转移到click事件处理程序中,然后使用支持渲染所需的数据更新组件状态,以便渲染不需要基于async/promise的函数callsRC,但图像已损坏。我很抱歉,我的回答中有一个小错误。请参阅在更新的渲染逻辑中使用imageSrc。这有用吗?
export const getDataURL = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = (error) => reject(error);
    });
};
state = {
  selectedPortifolio: {},
  portflioFiles: [],
  portflioImages : [] // Extend state with arrage for image data
}
addPortfolio = () => {
        if (
            this.state.selectedPortifolio &&
            this.state.selectedPortifolio.file
        ) {
            let items = this.state.portflioFiles;
            let images = this.state.portflioImages;
            items.push(this.state.selectedPortifolio);

            // Resolve promise outside of render-logic. Once data 
            // required for rendering is available, update state
            // to trigger a re-render
            getDataURL(this.state.selectedPortifolio).then((image) => {
                this.setState({ 
                  selectedPortifolio: {}, 
                  portflioFiles: items,
                  // Add resolved image to portflioImages images array
                  portflioImages : images.concat([image]) 
            });
          });
        }
    };
{this.state.portflioImages.length > 0 ? (
    /* map portflioImages directly to image without promise */
    this.state.portflioImages.map((imageSrc, index) => {
        return (
            <div className="portfolio-file" key={index}>
                <img src={imageSrc} alt={item.filename} />
            </div>
        );
    })
) : (
    <div></fdv>
)}