'Having issues rendering arrays of URLs in FlatLists in React Native
I am using Firebase v9 and React Native. I have one function and flatlist that is in charge of pulling and rendering group member data, and another function and flatlist that is in charge of rendering group posts. There are several issues going on here, but I would appreciate guidance on any part. I've been looking into this for a week.
The problem that I'm having is that the second flatlist is not rendering any images. I know that the styling is right because I've tried it with test data and I know that the URLs are being grabbed because I have can print a report of them. I've tried changing the way (item) is destructured, changing the renderItem functions, changing the parameters, and many more strategies, but nothing has worked.
I think it may have to do with the way that I'm storing my URLs in state and the temporary arrays I'm using. I'm also having the problem that the data doesn't load for the first flatlist when I first go to the screen, although it prints the right URLs. When I jump out and then go back to screen, the first flatlist renders the group members data (although the images are out of order sometimes). The data just prints out as Array [].
const MyGroupScreen = ({route, navigation}) => {
const { groupName, groupID } = route.params;
const [memNameLogs, setMemNameLogs] = useState([]);
const [memIDLogs, setMemIDLogs] = useState([]);
const [memImagesLogs, setMemImagesLogs] = useState([]);
const [memberCount, setMemberCount] = useState(0);
const [postIDLogs, setPostIDLogs] = useState([]);
const [postImagesLogs, setPostImagesLogs] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const getGroupInfo = async () => {
let memberIDs = [];
let memberNames = [];
let memberImages = [];
let userGroupsRef = collection(db, "groups", groupID, "members");
onSnapshot(userGroupsRef, (querySnapshot) => {
querySnapshot.forEach((document) => {
memberIDs.push(document.id)
onSnapshot(doc(db, "users", document.id), (snapshot) => {
const one = snapshot.data();
const two = one.firstName;
const three = one.lastName;
const four = two + ' ' + three;
memberNames.push(four);
});
const pathReference = ref(storage, 'userProfileImage/' + document.id);
getDownloadURL(pathReference)
.then((url) => {
memberImages.push(url);
})
});
setMemberCount(memberIDs.length);
setMemIDLogs(memberIDs);
setMemNameLogs(memberNames);
setMemImagesLogs(memberImages);
})
};
const getGroupPosts = async () => {
let postIDs = [];
let postImages = [];
let userPostsRef = collection(db, "groups", groupID, "posts");
onSnapshot(userPostsRef, (querySnapshot) => {
querySnapshot.forEach((document) => {
postIDs.push(document.id)
const postPathReference = ref(storage, 'posts/' + document.id + '/' + document.id + 0);
getDownloadURL(postPathReference)
.then((url) => {
postImages.push(url);
})
})
setPostIDLogs(postIDs);
setPostImagesLogs(postImages);
})
}
const [isFetching, setIsFetching] = useState(false);
const fetchData = () => {
getGroupPosts();
setIsFetching(false);
};
const onRefresh = () => {
setIsFetching(true);
fetchData();
};
useEffect(() => {
getGroupInfo();
getGroupPosts();
setIsLoading(false);
}, [])
const renderMembers = ({ item, index }) => (
<TouchableOpacity style={styles.memberInfo} onPress={()=>navigation.navigate('otherprofile', {userID: memIDLogs[index]})}>
<View style={{paddingBottom: 12}}>
<Image source={{uri: item}} style={styles.memberPicture}/>
</View>
<Text style={styles.memberName}>{memNameLogs[index]}</Text>
</TouchableOpacity>
);
const renderContent = ({ item, index }) => (
<TouchableOpacity onPress={()=>navigation.navigate('viewcontent')}>
<Image source={{uri: item}} style={styles.image}/>
</TouchableOpacity>
);
return (
<View style={styles.container}>
<View style={{alignItems:'center', width: width}}>
<View style={styles.groupBar}>
<View style={{flexDirection: 'row', flex: 1, justifyContent:'space-between', alignItems:'center'}}>
<View style={{flexDirection: 'row'}}>
<Text style={styles.groupName}>{groupName}</Text>
<Text style={styles.groupSize}>({memberCount})</Text>
</View>
</View>
<TouchableOpacity>
<Entypo name="menu" size={32} color={'#CACADB'}/>
</TouchableOpacity>
</View>
</View>
<FlatList
data={memImagesLogs}
renderItem={(item, index) => renderMembers(item, index)}
keyExtractor={item => item.id}
horizontal
showsHorizontalScrollIndicator='false'
style={{flex: 1}}
contentContainerStyle={{paddingTop: 12, paddingLeft: 24, backgroundColor: Colors.light.base, width: width}}
/>
<View style={{backgroundColor: Colors.light.base, height: 76, width: '100%', flexDirection:'row', alignItems:'center'}}>
<View style={{marginVertical: 36, marginLeft: 36, width: '15%', borderRadius: 15, height: 4, backgroundColor: '#CACADB'}}/>
</View>
<FlatList
data={postImagesLogs}
renderItem={(item, index) => renderContent(item, index)}
keyExtractor={item => item.id}
showsHorizontalScrollIndicator='false'
contentContainerStyle={{ paddingTop: 0, alignItems: 'center', justifyContent: 'flex-start'}}
columnWrapperStyle={{backgroundColor:Colors.light.base, width: width, justifyContent:'center'}}
style={{width: width}}
numColumns={4}
onRefresh={onRefresh}
refreshing={isFetching}
//extraData={postImages}
ListFooterComponent={()=>
<View style={{backgroundColor: Colors.light.base, height: '100%', width: width}}/>}
/>
<TouchableOpacity style={styles.addGroupButton} onPress={()=> navigation.navigate('newgroup', {screen: 'invitegroup', params: {groupID: groupID}})}>
<FontAwesome5 name='user-plus' size={20} color={Colors.light.base}/>
</TouchableOpacity>
</View>
);
}
export default MyGroupScreen;
Solution 1:[1]
In your useEffect(), you are calling getGroupPosts() which is an async function without an await or a .then()/.catch(). This is resulting in a behavior that will work sometimes work and not work. My suggestion is to call all async functions in your useEffect() like this:
getGroupInfo().catch(e => console.log(e));
getGroupPosts().catch(e => console.log(e));
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | man517 |
