【问题标题】:Performing firestore query in renderItem of FlatList to pass data to return Child在 FlatList 的 renderItem 中执行 firestore 查询以传递数据以返回 Child
【发布时间】:2021-09-08 04:41:37
【问题描述】:

这是一个学校项目,我被一个 bug 卡住了超过 12 个小时...

上下文是用户接受来自发件人的聊天请求,然后,当我返回 聊天 选项卡时,会创建并显示一个新的聊天“房间”。所有这些都在TabNavigator 中完成。

我的预期结果是当我作为用户接受传入的聊天请求。

问题是我试图从firestore 获取发件人的数据,但我一直未定义它的数据。我对应用程序的初始加载从 firestore 获取所有用户数据并加载 Redux 存储。

流程: 发件人发送聊天请求 -> 更新 firestore 并且正在监听更改 -> 收件人看到一个新的聊天请求(这有效) -> 接受 -> 为发件人和收件人创建了新的聊天“房间”(应该自动显示)

我尝试不获取未定义发件人的方式:

  1. 接受聊天请求,更新firestore,然后更新 Redux 存储。从“假定”更新的 Redux 存储中检索所有用户数据。但它是未定义的
  2. 编写了一个监听器来监听 firestoreusers 集合的变化,但在呈现 FlatList 中的项目时它会慢 1 步,并且我得到未定义的发件人数据
  3. 编写条件检查来检查发件人的数据是否未定义,如果是,则执行直接firestore 查询以从users 集合中获取发件人的数据。但我仍然不确定。

我怀疑所有这些都是由于 FlatList 再次重新渲染,但我不确定如何控制它。

我确实在FlatList 中为道具extraData 指定了一个状态。

我已经用尽了所有可能的方法,做了所有的研究,我已经筋疲力尽了。

感谢您的帮助,非常感谢。

这里是ChatsOverviewScreen,清理了不必要的代码:

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

  const userData = useSelector(state => state.user.userData);
  // const usersData = useSelector(state => state.users.usersData);
  const [initial, setInitial] = useState(true);
  const [chats, setChats] = useState([]);
  const [chatsLatestMsg, setChatsLatestMsg] = useState([]);
  const [usersData, setUsersData] = useState([]);

  // To listen for any update in Users collection
  // and then update usersData state
  useEffect(() => {
    const usersDataListener = firebase
      .firestore()
      .collection('users')
      .onSnapshot(querySnapshot => {
        let data = [];

        querySnapshot.forEach(doc => {
          if (doc.id !== currentUid) {
            data.push({ id: doc.id, ...doc.data() });
          }
        });

        setUsersData(data);
      });

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

  // To listen for any chat created for current user
  useEffect(() => {
    const chatsListener = firebase
      .firestore()
      .collection('users')
      .doc(firebase.auth().currentUser.uid)
      .onSnapshot(querySnapshot => {
        const latestChats = querySnapshot.data().chats;
        setChats(latestChats);
      });

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

  // useEffect(() => {
  //   getUsers();
  // }, [chats]);

  // const getUsers = async () => {
  //   const querySnapshot = await firebase.firestore().collection('users').get();

  //   let temp_users = [];

  //   querySnapshot.forEach(doc => {
  //     if (currentUid !== doc.id) {
  //       temp_users.push({ id: doc.id, ...doc.data() });
  //     }
  //   });

  //   setUsersData(temp_users);
  // };

  return (
    <SafeAreaView style={styles.parentContainer}>
      <FlatList
        data={chats}
        renderItem={({ item }) => {
          let peer;
          peer = usersData.filter(data => data.chats.includes(item))[0];
          let latestChat =
            chatsLatestMsg.length > 0
              ? chatsLatestMsg.filter(data => data.chatId === item)[0]
              : {};

          // console.log('before condition', peer);

          // if (peer === undefined) {
          // firebase
          //   .firestore()
          //   .collection('users')
          //   .where('chats', 'array-contains', item)
          //   .get()
          //   .then(querySnapshot => {
          //     let data = [];

          //     querySnapshot.forEach(doc => {
          //       if (doc.id !== currentUid) {
          //         data.push({ id: doc.id, ...doc.data() });
          //       }
          //     });

          //     peer = data.filter(user => user.chats.includes(item))[0];

          //     console.log('undefined', peer);

          //     return (
          //       <ChatItem
          //         key={item}
          //         currentUid={userData.id}
          //         latestChat={latestChat}
          //         chatId={item}
          //         peer={peer}
          //         onPress={navigateChat}
          //       />
          //     );
          //   });
          // }

          console.log('!undefined', peer);

          return (
            <ChatItem
              key={item}
              currentUid={userData.id}
              latestChat={latestChat}
              chatId={item}
              peer={peer} // I keep getting undefined peer right here!
              onPress={navigateChat}
            />
          );
        }}
        keyExtractor={item => item}
        extraData={chats}
      />
    </SafeAreaView>
  );
};

最后,ChatItem

const ChatItem = ({ peer, currentUid, chatId, onPress, latestChat }) => {
  let message = '',
    timestamp = '',
    id = '';

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

  return (
    <Pressable
      style={styles.cardContainer}
      onPress={() =>
        onPress({
          peerData: peer,
          chatId: chatId,
          id: peer.id,
          name: peer.name,
          imagePath: peer.imagePath
        })
      }
    >
      <Layout style={styles.avatarContainer}>
        {peer.imagePath.length > 0 ? (
          <Image source={{ uri: peer.imagePath }} style={styles.avatar} />
        ) : (
          <UserAvatar name={peer.name} size={50} fontSize={22} />
        )}
      </Layout>
      <Layout style={styles.detailsContainer}>
        <Layout style={styles.topChatContainer}>
          <Layout style={styles.nameContainer}>
            <Text category='h6' style={styles.name}>
              {peer.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>
  );
};

【问题讨论】:

    标签: javascript firebase react-native react-redux react-native-flatlist


    【解决方案1】:

    如果我的眼睛不说谎,我找不到任何与 redux 相关的东西。你把你的功能组件连接到 redux 了吗?

    一般来说,您是否也从 Firestore 获取数据?只是确保

    更新: 如果您确实从 firestore 获取数据并且您在 redux 中有数据,请执行条件渲染。

    return(
         <>
        {
           chatData.length > 0 ?
           <FlatList .../> :
           <ActivityIndicator .../> // It is the spinner
        }
        </>
    
    )
    

    确保重新渲染屏幕。

    【讨论】:

    • 我之前在将数据从 redux 存储(过滤 usersData)传递到 ChatItem 时遇到问题。是的,当我在 useEffect 中打印 usersData 时,我得到了数据。是的,我也得到数据!整个问题是,我没有足够快地获得 ChatItem 所需的数据。抱歉,上面的这些代码非常混乱。我重做了。以上只是正在发生的事情的一个小背景。很乱,我道歉
    • 它可能有一些错误。可能您还需要使用允许重新渲染屏幕的状态布尔值。无论如何,条件渲染是我认为的关键
    • 说实话,我更愿意从现在开始工作,stackoverflow.com/questions/68135388/…。我问题中的上述代码并不完全可持续。我依靠 redux 和 firestore,我陷入了巨大的混乱。你介意把这个带到别的地方聊天吗?
    • 我宁愿将 convos 保留在 stackoverflow 中。如果您仍然遇到代码问题,只需将它们发布在该链接中即可。我会尽力提供帮助
    • np 丹尼!我明白。是的,我只是想从stackoverflow.com/questions/68135388/… 开始工作,并使用 2 个钩子 - useStateuseEffect。会再次更新你!现在是凌晨 308 点。我快死了,哈哈。编辑:我想我要先去睡觉了,非常疲惫。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 2023-04-05
    • 1970-01-01
    • 2023-02-17
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    相关资源
    最近更新 更多