Как добавлять данные при повторной выборке

#reactjs #firebase #google-cloud-firestore

#reactjs #firebase #google-облако-firestore

Вопрос:

У меня возникли проблемы с добавлением моих данных, когда я вызываю свой метод выборки во второй раз. При первоначальном рендеринге мой компонент извлекает данные из моей базы данных и сохраняет их в моем состоянии followingData. Затем, когда я прокручиваю страницу вниз, я снова вызываю свою функцию fetchData, но вместо того, чтобы добавлять мои новые данные в состояние followingData, она заменяет их, и теперь на моем экране отображаются только новые данные.

Вот код:

 function Following({route, navigation}) {
  const [followingData, setfollowingData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [lastVisible, setLastVisible] = useState();

  const fetchData = () => {
    const dataaRef = firestore().collection('usernames');
    const dataRef = firestore().collection('usernames');

    dataRef
      .doc(route.params.username.toLowerCase())
      .collection('Following')
      .onSnapshot(() => {
        dataaRef
          .doc(route.params.username.toLowerCase())
          .collection('Following')
          .orderBy('followedAt')
          .startAfter(lastVisible || 0)
          .limit(7)
          .get()
          .then((snapshot) => {
            snapshot.empty
              ? null
              : setLastVisible(
                  snapshot.docs[snapshot.docs.length - 1].data().followedAt,
                );
            let promises = [];
            snapshot.forEach((doc) => {
              const data = doc.data();
              promises.push(
                data.path.get().then((res) => {
                  const userData = res.data();
                  return {
                    profileName: doc.id ? doc.id : null,
                    displayName: userData.displayName
                      ? userData.displayName
                      : null,
                    followerCount:
                      userData.followers !== undefined ? userData.followers : 0,
                    followingCount:
                      userData.following !== undefined ? userData.following : 0,
                    imageUrl: userData.imageUrl ? userData.imageUrl : null,
                  };
                }),
              );
            });
            Promise.all(promises).then((res) => {
              setfollowingData(res);
            });
            setLoading(false);
          });
      });
  };

  useEffect(() => {
    const dataRef = firestore().collection('usernames');

    const cleanup = fetchData();

    return cleanup;
  }, [route.params.username]);

  return (
    <>
      <View
        style={styles}>
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Icon name="menu" color="#222" size={30} />
        </TouchableOpacity>
        <Text style={{left: width * 0.05}}>Following</Text>
      </View>

      {loading ? (
        <ActivityIndicator size="large" color="black" />
      ) : (
        <>
          <FolloweringScreens
            data={followingData}
            screen={'Following'}
            username={route.params.username}
            navigation={navigation}
            fetchData={fetchData}
          />
        </>
      )}
    </>
  );
}

export default Following;
 

Дочерний компонент выглядит следующим образом, где fetchData вызывается при прокрутке до конца:

 function FolloweringScreens({
  data,
  screen,
  username,
  navigation,
  fetchData,
  setNext,
}) {

  return (
    <>
      <FlatList
        scrollEnabled={true}
        onEndReachedThreshold={0}
        onEndReached={fetchData} <<-- CALLING FETCHDATA AGAIN TO GET MORE DATA
        data={data}
        keyExtractor={(i, index) => index.toString()}
        renderItem={({item, index}) => {
          return (
                  (I use my data here)
          );
        }}
      />
    </>
  );
}

export default FolloweringScreens;
 

Ответ №1:

Если вы просто хотите добавить новые данные, то лучше, если вы используете функцию обратного вызова в вашем setState:

 Promise.all(promises).then(res => {
  setfollowingData(oldState => ({...oldState, ...res}));
});
 

Здесь вы берете все значения из старого состояния, помещаете их в новый объект и добавляете к нему новые данные. Если ваше состояние является массивом, вам придется заменить {} на []:

 Promise.all(promises).then(res => {
  setfollowingData(oldState => ([...oldState, ...res]));
});
 

ОБНОВЛЕНИЕ: добавлен пример

Комментарии:

1. Это возвращает данные следующим образом: {«0»: {Первый набор данных}, «1»: {второй набор данных}, «2»: {второй набор данных}, «3»: {второй набор данных}, «4»: {второй набор данных}} но мне нужны данные в массиве, чтобы я мог использовать их в flatlLst.

2. Вот почему вы должны заменить фигурные скобки на скобки массива. Я обновлю свой ответ.

3. Вы уверены, что это массив объектов? Сообщение об ошибке звучит так, как будто это что-то другое. Можете ли вы записать ответ в консоль и добавить его в свой вопрос?

4. Хорошо, но вы всегда получаете массив обратно, поэтому сообщение об ошибке в этом случае не имеет смысла. Чтобы решить вашу проблему, связанную с быстрым запуском функции, вы могли бы создать функцию debounce: freecodecamp.org/news/javascript-debounce-example

5. Я такой идиот. Итак, причина, по которой я получал эту ошибку, заключается в том, что начальное состояние было пустым. После изменения начального состояния на [] теперь оно работает. Извините, что потратили ваше время, и большое вам спасибо за вашу помощь, ценю это, спасибо, сэр!!!