从 Firestore 动态获取数据时,RenderItem 未呈现 [英] RenderItem not rendering when dynamically getting data from firestore

查看:50
本文介绍了从 Firestore 动态获取数据时,RenderItem 未呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ChatsOverview 屏幕包含呈现 ChatItems 的 FlatList.FlatList 的 data 属性是一个 chatId 数组.这些 id 将用于 firestore 查询以获取其中包含 ChatItem 所需数据的文档.

A ChatsOverview screen contains a FlatList that renders ChatItems. The FlatList's data prop is an array of chatIds. These ids will be used in a firestore query to get a document with data in it required by the ChatItem.

我的问题是 ChatItem 没有从 firestore 查询中获取返回的数据,而当我从 get() 记录返回数据时,我得到的数据是需要.

My issue is that the ChatItem is not getting the returned data from the firestore query whereas when i logged the return data from get() i get the data that i require.

我尝试创建一个单独的函数来呈现 ChatItem 并且该函数是异步的,尝试等待 firestore 返回数据但无济于事..

I have tried creating a separate function to render the ChatItem and this function is async, to try and wait for firestore to return the data but to no avail..

每次将用户添加到聊天中时,FlatList 都应该重新呈现(chatIds,即 chatIdsListener).

The FlatList ought to re-render everytime the user is being added to a chat (chatIds i.e. the chatIdsListener).

我在代码中做了一些注释,以显示其打印/数据按预期显示的位置.

I made some remarks in the code to show where it's printing/data is showing as expected.

聊天概览屏幕:

const ChatsOverviewScreen = ({ navigation }) => {
  const currentUid = firebase.auth().currentUser.uid;

  const [chatIds, setChatIds] = useState([]);

  useEffect(() => {
    const chatIdsListener = firebase
      .firestore()
      .collection('users')
      .doc(currentUid)
      .onSnapshot(querySnapshot => {
        setChatIds(querySnapshot.data().chats);
      });

    return () => chatIdsListener();
  }, []);

  const renderChatItem = async chatId => {
    const querySnapshot = await firebase
      .firestore()
      .collection('chats')
      .where('chatId', '==', chatId)
      .get();

    querySnapshot.forEach(doc => {
      if (doc.id === chatId) {
        console.log('rendering chatItem', doc.data());

        return (
          <ChatItem
            key={chatId}
            chatData={doc.data()}
            currentUid={currentUid}
          />
        );
      }
    });
  };

  return (
    <SafeAreaView style={styles.parentContainer}>
      <Layout style={styles.chatsContainer}>
        {chatIds.length > 0 ? (
          <FlatList
            data={chatIds}
            renderItem={({ item }) => {
              firebase
                .firestore()
                .collection('chats')
                .where('chatId', '==', chatId)
                .get()
                .then(querySnapshot => {
                  querySnapshot.forEach(doc => {
                    if (doc.id === item) {
                      console.log('rendering chatItem', doc.data()); // logs here

                      return (
                        <ChatItem // nothing being logged here for 'chatData'
                          key={item}
                          chatData={doc.data()}
                          currentUid={currentUid}
                        />
                      );
                    }
                  });
                });
              // renderChatItem(item);
            }}
            keyExtractor={item => item}
            extraData={chatIds}
          />
        ) : (
          <Layout style={styles.emptyContainer}>
            <Text style={styles.emptyText}>
              {`Sorry, we can't find any chats.\nHead to the Team Up screen to get started!`}
            </Text>
          </Layout>
        )}
      </Layout>
    </SafeAreaView>
  );
};

聊天项目:

const ChatItem = ({ chatData, currentUid, onPress }) => {
  const { name, imagePath } = chatData.participants.filter(
    user => user.id !== currentUid
  )[0];

  console.log(name, imagePath); // not printing anything

  let message = '',
    timestamp = '',
    id = '';

  if (chatData.latestMessage !== undefined) {
    message = chatData.latestMessage.message;
    timestamp = chatData.latestMessage.timestamp;
    id = chatData.latestMessage.id;
  }

  return (
    <Pressable style={styles.cardContainer} onPress={() => onPress({})}>
      <Layout style={styles.avatarContainer}>
        {imagePath.length > 0 ? (
          <Image source={{ uri: imagePath }} style={styles.avatar} />
        ) : (
          <UserAvatar name={name} size={50} fontSize={22} />
        )}
      </Layout>
      <Layout style={styles.detailsContainer}>
        <Layout style={styles.topChatContainer}>
          <Layout style={styles.nameContainer}>
            <Text category='h6' style={styles.name}>
              {name}
            </Text>
          </Layout>
          <Layout style={styles.timeContainer}>
            {timestamp.length > 0 && (
              <Text>{dayjs(timestamp).format('h:mm A')}</Text>
            )}
          </Layout>
        </Layout>
        <Layout style={styles.bottomChatContainer}>
          {message.length > 0 ? (
            <Text numberOfLines={1}>
              {currentUid === id ? `You: ${message}` : message}
            </Text>
          ) : (
            <Text>Click on here to start a conversation!</Text>
          )}
        </Layout>
      </Layout>
    </Pressable>
  );
};

感谢您的任何意见,谢谢

I appreciate any inputs, thank you

推荐答案

如果我没记错的话,renderItem 属性只是为了渲染 UI.在那里有异步任务不是一个好主意.我建议过滤钩子中的数据,然后将过滤后的数据传递给 renderItem

If I am not wrong, renderItem property is just for rendering the UI. It is not a great idea to have async tasks there. I would suggest filtering the data in hooks an then pass the filtered data into renderItem

这篇关于从 Firestore 动态获取数据时,RenderItem 未呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆