#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. Я такой идиот. Итак, причина, по которой я получал эту ошибку, заключается в том, что начальное состояние было пустым. После изменения начального состояния на [] теперь оно работает. Извините, что потратили ваше время, и большое вам спасибо за вашу помощь, ценю это, спасибо, сэр!!!