我正在使用firebase在我的项目中做反应。代码如下
var storage = firebase.storage()
var storageRef = storage.ref();
export default class WallPics extends Component {
constructor(props){
super(props)
this.state={
images : []
}
}
componentWillMount(){
var imgArr=[]
storageRef.listAll()
.then(allPics=>{
allPics.items.forEach(function (picRef){
picRef.getDownloadURL()
.then(function (url){
imgArr.push(
<img src={url} alt="pics" />
)
})
})
this.setState({
images : imgArr
})
})
}
render() {
return (
<div>
{this.state.images}
</div>
)
}
}
在上面的代码中,我从Firebase存储中获取所有图片引用,并将图片下载URL附加到imgArr
。在将所有URL附加到imgArr
之后,我想更改状态。但是这里this.setState
变空了imgArr
。但是我想用图片下载URL的imgArr
更改状态值。我现在该怎么做?
答案 0 :(得分:2)
getDownloadURL是异步的吗?如果是,那么您应该等待诺言解决
尝试这样的事情?
async componentDidMount() {
let imgArr=[]
let allPics = await storageRef.listAll()
let promises = []
allPics.items.forEach((picRef) => {
promises.push(picRef.getDownloadURL())
})
const urls = await Promise.all(promises);
for(let url of urls){
imgArr.push(<img src={url} alt="pics" />)
}
this.setState({images : imgArr})
}
答案 1 :(得分:2)
根据React官方文件here,我不建议您直接将组件置于状态:
状态应包含组件的事件处理程序可能更改以触发UI更新的数据。
还明确指出,组件不应进入状态:
this.state应该只包含表示UI状态所需的最少数据量。因此,它不应包含:
反应组件:基于基础道具在render()中构建它们,并 状态。
因此,我建议您首先将fetch操作提取到一个单独的函数中以更好地阅读,并设置需要声明的网址(而不是组件)。
fetchPics = async() => {
const allPics = await storageRef.listAll();
const allUrls = await allPics.items.map(picRef => picRef.getDownloadURL());
// here I use async, you might also use promise.all()
// as stated in @Alexandr Zavalii's answer
this.setState({ images : allUrls })
}
componentDidMount() {
this.fetchPics();
}
最后,在render函数中使用url渲染组件。
render() {
return (
<div>
{this.state.images.map(url => <img src={url} alt="pics" />)}
</div>
)
}