javascript - setState 不会在函数范围之外保持状态
问题描述
firebase 存储 API 参考中的 listFilesAndDirectories 函数用于获取已保存在存储桶中的图像的下载 URL,但使用 setState 将状态保留为 url,直到作为图像 uri 传递不起作用
import React, {setState} from 'react';
import {DrawerActions, useNavigation} from '@react-navigation/native';
const Gallery: () => React$Node = () => {
const navigation = useNavigation();
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
// call getDownloadURL on every object reference
ref.getDownloadURL().then(url => {
setState({url: url});
console.log(
`File is referenced from :\n ${storageReference}:\n\n Image URL is:\n ${url}`,
);
console.log(`url is available here ${url}`);
//after this point URL is no longer available
});
});
if (result.nextPageToken) {
return listFilesAndDirectories(reference, result.nextPageToken);
}
return Promise.resolve();
});
}
const storageReference = firebase
.storage()
.refFromURL('gs://app404.com/images');
listFilesAndDirectories(storageReference).then(() => {
console.log('Started listing image download urls');
});
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<View style={SharedStyles.header}>
<TouchableOpacity
onPress={() => {
navigation.dispatch(DrawerActions.openDrawer());
}}>
<Hamburg />
</TouchableOpacity>
<Header title="Gallery" />
</View>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={styles.container}>
<View style={styles.sectionContainer}>
<View>
<Text>
Welcome to the Abulad Gallery! Come back for more content....
</Text>
<Image
source={{
uri: {url}//url is not defined
}}
style={styles.fetchedImage}
/>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
</>
);
};
需要一种即使在函数之外也能保持状态的方法,以便可以显示图像。谢谢
解决方案
您正在尝试使用钩子而没有真正正确地使用它们。useState
是 React 中的一个初始化函数,它本质上是创建一个初始状态并在 React 执行堆栈中创建一个引用,当set*
调用返回的函数时,节点应该重新渲染。
这是你如何使用useState
:
import { useState} from "react";
const Gallery: () => {
const navigation = useNavigation();
const [ downloadUrl, setDownloadUrl ] = useState({ url: undefined });
console.log(downloadUrl);
// should be {url: undefined} on 1st render, {url: <some url>} on subsequent renders
// This should be refactored to `useEffect` to take advantage of async operations in React
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
// call getDownloadURL on every object reference
ref.getDownloadURL().then(url => {
// An array would be better here, but this is just for example
setDownloadUrl({ url }); // creates obj {url: url}, will cause a re-render once execution is complete
console.log(
`File is referenced from :\n ${storageReference}:\n\n Image URL is:\n ${url}`,
);
console.log(`url is available here ${url}`);
//after this point URL is no longer available
});
});
if (result.nextPageToken) {
return listFilesAndDirectories(reference, result.nextPageToken);
}
return Promise.resolve();
});
}
// ...
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<View style={SharedStyles.header}>
<TouchableOpacity
onPress={() => {
navigation.dispatch(DrawerActions.openDrawer());
}}>
<Hamburg />
</TouchableOpacity>
<Header title="Gallery" />
</View>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={styles.container}>
<View style={styles.sectionContainer}>
<View>
<Text>
Welcome to the Abulad Gallery! Come back for more content....
</Text>
<Image
source={{
uri: { downloadUrl.url }//url is not defined
}}
style={styles.fetchedImage}
/>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
</>
);
}
完成该工作后,您可以更新图像占位符以使用微调器图标或其他加载图标,例如。
{ !downloadUrl.url ? <Spinner /> : (
<div>...</div>
)}
推荐阅读
- r - R代码:当我在R中绘制包含多条线的折线图时,其中一条无法完全显示
- android - Android 动态交付:无法解析以下类的超类型;未解决的超类型:android:support:v7:app:AppCompatActivity
- android - 指定的孩子已经有一个父母。在我的聊天应用程序中,您必须首先在孩子的父母上调用 removeView()
- angular - 如何测试可观察流?
- c# - 如何从mvc中的cshtml视图将参数传递给控制器
- bootstrap-4 - 如何通过先前选择的项目 ID 填充下拉列表
- css - 如何告诉 Stylus 不要将 CSS 属性解释为 mixin?
- python - 如何创建基于资源的策略?
- excel - 在字符串 VBA 中搜索数字
- azure - 互联网出口的 Kubernetes 网络策略