为什么使用FileReader读取文件内容时setState不起作用?

问题描述 投票:1回答:1

我正在输入可以预先显示的多个图像。

要处理多个图像,我将它们放置在组件状态的数组中,并映射预可视化的图像,但是当我从输入中选择图像并设置状态this.setState({imgArray: newArray})时,this.state.array.map(image=><img src={image}/>)不重新渲染

代码示例:

export default class posts extends Component {
    state = {
        fotos: ["/iconos/img.svg"] //If there are not img selected, it renders one image icon
    }
    onUploadVarious = e=>{
        let newArray = []
        Object.values(e.target.files).map(file=>{
            let nuevo = new FileReader()                                                
            nuevo.onload = event=> newArray.push(event.target.result)
            nuevo.readAsDataURL(file)}
        )
        this.setState({fotos: newArray}) //the state is set correctly
    }

渲染:

<div className=" border rounded" style={{"height":"30%", "overflow":"auto"}}>
    {this.state.fotos.map(foto=>
    <img src={foto||"/iconos/img.svg"}
    id="arch-preview"/>)} //it doesn't re-render when fotos state is changed
</div>

//input
<div className="mt-auto">
    <input multiple="multiple" type="file" 
    onChange={this.onUploadVarious} 
    className="form-control-file" name="file" />
</div>
javascript reactjs render setstate
1个回答
0
投票

FileReader读取文件内容异步

由于这种异步性质,正在设置状态,即在[this.setState({fotos: newArray})]中设置数据URL之前的newArray,即newArray.push(event.target.result)

这就是所选文件没有显示]的原因>。

要修复它,您可以使用创建Promise,该文件在每个文件的load事件后得到解析。并使用Promise.all,将在每个Promise解决后解决,然后使用setState

readAsDataURL = (file) => {
  return new Promise((resolve, reject) => {
    const fr = new FileReader()
    fr.onerror = reject
    fr.onload = function () {
      resolve(fr.result)
    }
    fr.readAsDataURL(file)
  })
}

onUploadVarious = (e) => {
  Promise.all(Array.from(e.target.files).map(this.readAsDataURL))
    .then((urls) => {
      this.setState({ fotos: urls })
    })
    .catch((error) => {
      console.error(error)
    })
}

This具有Promise及其执行顺序

的一些很好的示例。还要检查this关于将FileReader与Promise一起使用。
© www.soinside.com 2019 - 2024. All rights reserved.