在 React Native 中渲染 FlatLists 中的 URL 数组时出现问题

发布于 2025-01-11 17:56:43 字数 6024 浏览 5 评论 0原文

我正在使用 Firebase v9 和 React Native。我有一个函数和平面列表负责提取和渲染组成员数据,另一个函数和平面列表负责渲染组帖子。这里存在几个问题,但我希望得到有关任何部分的指导。我已经研究这个问题一周了。

我遇到的问题是第二个平面列表没有渲染任何图像。我知道样式是正确的,因为我已经用测试数据尝试过,并且我知道 URL 正在被抓取,因为我可以打印它们的报告。我尝试过更改(项目)的解构方式、更改 renderItem 函数、更改参数以及更多策略,但没有任何效果。

我认为这可能与我在状态中存储 URL 的方式以及我正在使用的临时数组有关。我还遇到一个问题,即当我第一次进入屏幕时,第一个平面列表的数据无法加载,尽管它打印了正确的 URL。当我跳出然后返回屏幕时,第一个平面列表呈现组成员数据(尽管图像有时是乱序的)。数据只是以 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;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

假装不在乎 2025-01-18 17:56:43

useEffect() 中,您正在调用 getGroupPosts(),它是一个不带等待或 .then() 的 async 函数/.catch()。这导致了一种有时有效有时无效的行为。我的建议是像这样调用 useEffect() 中的所有异步函数:

getGroupInfo().catch(e => console.log(e));
getGroupPosts().catch(e => console.log(e));

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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文