React Native FlatList不渲染仅显示ActivityIndicator问题解决
React Native FlatList 无法渲染Firebase数据(仅显示ActivityIndicator)
问题根源
- 状态类型不匹配:
loca初始化为数组[],但在Get函数中用setLoca赋值了单个对象,导致loca变成对象而非数组。此时loca.length为undefined,永远不满足loca.length > 0的判断,所以一直显示ActivityIndicator。 - 循环中重复覆盖状态:
querySnapshot.forEach里每次调用setLoca都会覆盖之前的状态,最终loca只会保留最后一个文档的数据,且setState是异步操作,console.log(loca)无法打印最新状态。 - 组件导入缺失:
home.js中使用了<Comp />但未导入comp.js组件,会导致渲染错误。 - 组件命名不规范:React组件名需首字母大写,否则会被当作普通HTML标签处理。
修复后的代码
home.js
// 导入Comp组件 import Comp from './comp'; export default function Second({navigation}) { const [loca, setLoca] = useState([]); // 新增加载状态,判断更严谨 const [isLoading, setIsLoading] = useState(true); const Get = async () => { try { const myDoc = collection(db, 'users'); const querySnapshot = await getDocs(myDoc); // 先将所有数据收集到数组 const userList = []; querySnapshot.forEach(doc => { console.log(doc.id, ' => ', doc.data()); userList.push({ id: doc.id, fname: doc.data().fname, }); }); // 一次性更新状态 setLoca(userList); } catch (error) { console.error('获取数据失败:', error); } finally { setIsLoading(false); } }; const Logout = () => { signOut(auth) .then(() => { console.log('log out'); navigation.navigate('Login'); }) .catch(error => { console.log(error); }); }; useEffect(() => { Get(); }, []); const renderItemm = ({item}) => <Comp title={item.fname} />; return ( <View style={styles.conn}> <ImageBackground source={image} resizeMode="cover" style={{flex: 1}}> <View style={{paddingHorizontal: 15}}> <View style={styles.box}> <View style={{justifyContent: 'space-between'}}> <Text>HOME</Text> <TouchableOpacity style={styles.box1} onPress={Logout}> <Text>dd</Text> </TouchableOpacity> <TouchableOpacity style={styles.box1} onPress={() => navigation.navigate('Third')}></TouchableOpacity> </View> </View> {/* 用加载状态判断,替代数组长度判断 */} {isLoading ? ( <ActivityIndicator /> ) : ( <FlatList data={loca} renderItem={renderItemm} keyExtractor={item => item.id} // 可选:空数据时显示提示 ListEmptyComponent={<Text>暂无用户数据</Text>} /> )} </View> </ImageBackground> </View> ); } const styles = StyleSheet.create({ conn: { flex: 1, }, tt: { color: 'white', backgroundColor: '#4DA69B', fontSize: 24, width: 80, height: 80, borderRadius: 40, alignItems: 'center', }, box: { marginTop: 10, flexWrap: 'wrap', flexDirection: 'row', }, end: { alignItems: 'flex-end', marginBottom: 10, }, box1: { width: 48, height: 48, borderRadius: 24, backgroundColor: '#67BE92', marginTop: 10, marginLeft: 10, alignItems: 'flex-end', }, boxxx: { backgroundColor: '#f9c2ff', padding: 20, marginVertical: 8, marginHorizontal: 16, }, });
comp.js
// 组件名首字母大写,符合React规范 const Comp = (props) => { return ( <View style={styles.conn}> <View style={styles.box}> <Text>{props.title}</Text> </View> </View> ); }; export default Comp; const styles = StyleSheet.create({ conn: { flex: 1, flexDirection: 'row', justifyContent: 'space-between', }, tt: { color: 'white', backgroundColor: '#4DA69B', fontSize: 24, width: 80, height: 80, borderRadius: 40, alignItems: 'center', }, box: { flex: 1, marginTop: 10, borderRadius: 10, width: '100%', height: 115, borderWidth: 1, borderColor: '#67BE92', backgroundColor: 'white', flexDirection: 'row', // 可选:添加内边距,避免文字贴边 padding: 10, }, end: { alignItems: 'flex-end', marginBottom: 10, }, box1: { width: 48, height: 48, borderRadius: 24, backgroundColor: '#67BE92', marginTop: 10, marginLeft: 10, }, });
关键修复点总结
- 先收集所有Firebase文档数据到数组,再一次性更新状态,避免重复覆盖和异步问题。
- 用
isLoading状态控制加载提示,比判断数组长度更可靠,还能处理空数据场景。 - 修复组件命名和导入问题,符合React规范。
内容的提问来源于stack exchange,提问作者Phatchara Sangkeaw
相关产品推荐
相关产品推荐

