我正在输入可以预先显示的多个图像。
要处理多个图像,我将它们放置在组件状态的数组中,并映射预可视化的图像,但是当我从输入中选择图像并设置状态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>
FileReader读取文件内容异步。
由于这种异步性质,正在设置状态,即在[this.setState({fotos: newArray})
]中设置数据URL之前的newArray
,即newArray.push(event.target.result)
。
这就是所选文件没有显示]的原因>。
要修复它,您可以使用创建Promise
,该文件在每个文件的load
事件后得到解析。并使用Promise.all
,将在每个Promise解决后解决,然后使用setState
:
的一些很好的示例。还要检查this关于将FileReader与Promise一起使用。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及其执行顺序