Trying to access items from an array in state - arrays

Im trying to access a array in my state in a function. I currently have filled the array like this:
loadFollowing() {
var newFollowing = this.state.following
const db = firebase.firestore()
db.collection('users')
.doc(this.state.uid)
.collection('following')
.get()
.then(snapshot => {
snapshot.forEach(doc => {
var newFollower = {
id: doc.id
}
newFollowing.push(newFollower)
})
this.setState({
following: newFollowing
})
})
then in another function im trying to access elements of this.state.following like this:
loadPosts() {
var newPostList = this.state.postList
var newFollowing = this.state.following
const db = firebase.firestore()
const postCollection = db.collection('posts')
for (let object of newFollowing) {
postCollection
.where('creatorId', '==', object.id)
.get()
.then(snapshot => {
snapshot.forEach(doc => {
var postItem = {
username: doc.data().username,
content: doc.data().content,
creatorId: doc.data().creatorId,
workoutId: doc.data().workoutId,
id: doc.id
}
newPostList.push(postItem)
})
})
this.setState({
postList: newPostList
})
}
But newFollowing turns up empty, does anyone know what to do?

Remove loadPosts() from componentDidMount() and call it once you setState in loadFollowing().
loadFollowing() {
var newFollowing = this.state.following
const db = firebase.firestore()
db.collection('users')
.doc(this.state.uid)
.collection('following')
.get()
.then(snapshot => {
snapshot.forEach(doc => {
var newFollower = {
id: doc.id
}
newFollowing.push(newFollower)
})
this.setState({
following: newFollowing
})
this.loadPosts();
})
}
loadPosts() {
var newPostList = this.state.postList
var newFollowing = this.state.following
const db = firebase.firestore()
const postCollection = db.collection('posts')
for (let object of newFollowing) {
postCollection
.where('creatorId', '==', object.id)
.get()
.then(snapshot => {
snapshot.forEach(doc => {
var postItem = {
username: doc.data().username,
content: doc.data().content,
creatorId: doc.data().creatorId,
workoutId: doc.data().workoutId,
id: doc.id
}
newPostList.push(postItem)
})
})
this.setState({
postList: newPostList
})
}

Related

A pending promise is returned from stripe.checkout.sessions.listLineItems each time

Here I am trying to get the data from the firebase and then use that id to retrieve items from stripe checkout.
But each time I try this I get a pending promise.
const colRef = collection(db, `users/${session.user.email}/orders`);
const q = query(colRef, orderBy("timestamp", "desc"));
const orders = await getDocs(q)
.then((snapshot) => {
snapshot.docs.forEach((sdoc) => {
orders.push({
id: sdoc.id,
items: stripe.checkout.sessions
.listLineItems(sdoc.id, {
limit: 100,
})
.then((res) => {
return res;
})
.catch((err) => console.log(err)),
});
});
return orders;
})
.catch((err) => console.log(err));
I have also tried with await but then my whole array is just returned empty
const colRef = collection(db, `users/${session.user.email}/orders`);
const q = query(colRef, orderBy("timestamp", "desc"));
orders = await getDocs(q)
.then((snapshot) => {
snapshot.docs.forEach(async (sdoc) => {
orders.push({
id: sdoc.id,
items: await stripe.checkout.sessions
.listLineItems(sdoc.id, {
limit: 100,
})
.then((res) => {
return res;
})
.catch((err) => console.log(err)),
});
});
return orders;
})
.catch((err) => console.log(err));
You'll need to combine the collection of promises with Promise.all. It will look like this:
const snapshot = await getDocs(q);
const orders = await Promise.all(snapshot.docs.map(async (sdoc) => {
const sessions = await stripe.checkout.sessions
.listLineItems(sdoc.id);
return {id: sdoc.id, items: sessions};
}));

Reactjs - Firebase : Cancel Old Requests

I'm new to Firebase Realtime Database, and i'm trying to implement a search field that allow users to search for other users and view their profiles.
The Problem Is:
I want to make the search realTime(on each input change).but whenever a new request's sent, the old request is still working in the backend which's causing unexpected behavior,i've wrapped this functionality in a useEffect Hook,old sideEffects has to be cleaned up to make the query results predictable,how can i abort the previous request.
useSearchOwner Custom Hook:
const useSearchOwner = () => {
const [{ SearchValue, SearchResult, Search }, dispatch] = useReducer(
reducer,
{
SearchValue: "",
SearchResult: "",
Search: false,
}
);
const isFirstRender = useRef(true);
const onChangeHandler = (e) =>
dispatch({
type: ACTIONS.UPDATE_SEARCH_VALUE,
payload: { searchValue: e.target.value },
});
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
dispatch({ type: ACTIONS.START_SEARCHING });
const DispatchQueryByResult = async () => {
const ArrayOfOwners = await FirebaseUtilityInstance.SearchOwnerResult(
SearchValue
);
dispatch({
type: ACTIONS.UPDATE_SEARCH_RESULT,
payload: { searchResult: ArrayOfOwners },
});
dispatch({ type: ACTIONS.STOP_SEARCHING });
return () => {
FirebaseUtilityInstance.SearchOwnerCleanup();
};
};
DispatchQueryByResult();
}, [SearchValue]);
useEffect(() => {
console.log(SearchResult);
}, [SearchResult]);
return {
onChangeHandler: onChangeHandler,
Query: SearchValue,
QueryResult: SearchResult,
isSearching: Search,
};
};
Firebase Method To Do Query:
SearchOwnerResult = async (Query) => {
const { firstName, lastName } = getFirstNameAndLastName(Query);
let ArrayOfOwners = [];
await this.Database()
.ref("users")
.orderByChild("UserType")
.equalTo("owner")
.once("value", (snapshot) => {
const OwnersContainer = snapshot.val();
const keys = Object.keys(OwnersContainer);
for (let i = 0; i < keys.length; i++) {
const CurrentOwner = OwnersContainer[keys[i]];
if (
CurrentOwner.FirstName === firstName ||
CurrentOwner.LastName === lastName
) {
ArrayOfOwners.push(OwnersContainer[keys[i]]);
}
}
});
return ArrayOfOwners;
};

push object to array react native

I need to get specific users who have the serviceClientID field in the firestore.
those that do, I insert it into the array and put it in my state chats (setChat).
but the problem is that only one user is entering my state and I have two users with this field.
why is only 1 entering and not 2?
code below:
firebase.auth().onAuthStateChanged(async ({ uid }) => {
const servicesCollection = await firestore()
.collection('Providers')
.doc(uid)
.collection('ServiceHistory')
.get();
servicesCollection.docs.forEach(async item => {
if (item.exists && item.data().serviceClientID) {
const clientsCollection = await firestore()
.collection('Clients')
.doc(item.data().serviceClientID)
.get();
// if (item.data().serviceClientID === clientsCollection.id) {
const values = {
id: clientsCollection.id,
name: clientsCollection.data().name.last,
uid,
};
const arr = [];
arr.push(values);
// }
console.log('arrayay', arr);
setChats(arr);
}
});
});
Cause every loop you empty an array.
You have to get the {arr} out of the function. then you need to push the data inside.
const firebaseFunc = () => {
let arr = [];
firebase.auth().onAuthStateChanged(async ({ uid }) => {
const servicesCollection = await firestore()
.collection('Providers')
.doc(uid)
.collection('ServiceHistory')
.get();
servicesCollection.docs.forEach(async item => {
if (item.exists && item.data().serviceClientID) {
const clientsCollection = await firestore()
.collection('Clients')
.doc(item.data().serviceClientID)
.get();
arr.push({
id: clientsCollection.id,
name: clientsCollection.data().name.last,
uid,
});
});
});
setChats(arr);
console.log('arrayay', arr);
}

implement the onSnapshot function for getting realtime updates in reactjs code

in my case I want to implement the onSnapshot function for getting realtime updates, so here's my sample code it's working now:
db.collection("Cities").onSnapshot((snapshot) => {
snapshot.docs.forEach((doc) => {
console.log(doc.data());
});
});
But now, how can I implement it to the following code
getMyInfo = () => {
db.collection("Cities")
.limit(8)
.get()
.then((docs) => {
if (!docs.empty) {
let AllCities = [];
docs.forEach(function (doc) {
const city = {
id: doc,
...doc.data(),
};
AllCities.push(city);
});
this.setState(
{
cities: AllCities,
},
() => {
this.setState({
isLoaded: true,
});
}
);
}
});
};
Thanks
You are saving all your cities into your state. Use it to add or update the new (or updated) cities.
Maybe you can try something like that :
db.collection("Cities").onSnapshot((snapshot) => {
snapshot.docs.forEach((doc) => {
const updatedCity = doc.data();
const cities = [...this.state.cities];
const index = this.state.cities.findIndex(c => c.id === updatedCity.id);
if (index >= 0) {
cities[index] = updatedCity;
} else {
cities.push(updatedCity);
}
this.setState({ cities });
});
});

How to make Async Await Function in React Native?

I want to create a function that is about uploading photo to Firebase Storage with react-native-fetch-blob. I'm using Redux and you can find action functions below:
My problem is that uploadImage function is not running like asynchronous. Firebase function is running before uploadImage, so application give me an error.
I think i can't make a asynchronous function. How can i fix it ?
uploadImage() function:
const uploadImage = async (imageSource, whereToUpload) => {
let imageURL = '';
const mime = 'image/jpg';
const { Blob } = RNFetchBlob.polyfill;
const { fs } = RNFetchBlob;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
console.log('URI =>', imageSource.uri);
let imgUri = imageSource.uri;
let uploadBlob = null;
const imageRef = firebase.storage().ref(whereToUpload + '/' + imageSource.fileName);
const uploadUri = Platform.OS === 'ios' ? imgUri.replace('file://', '') : imgUri;
await fs.readFile(uploadUri, 'base64')
.then((data) => Blob.build(data, { type: `${mime};BASE64` }))
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
// eslint-disable-next-line no-return-assign
return imageURL = imageRef.getDownloadURL();
})
.catch((error) => {
console.log(error);
});
return imageURL;
};
and the main action is:
export const addProjectGroup = (
myUser,
groupName,
groupDescription,
groupProfilePic,
) => dispatch => {
const groupProfileFinalPic = async () => {
let finalGroupPicture = { landscape: '' };
if (_.isEmpty(groupProfilePic.src)) {
await uploadImage(groupProfilePic, 'groupPictures').then((imageURL) => {
console.log('İŞLEM TAMAM!');
console.log('SELECTED IMAGE URL =>', imageURL);
finalGroupPicture.landscape = imageURL;
});
} else {
finalGroupPicture.landscape = groupProfilePic.src.landscape;
}
return finalGroupPicture;
};
console.log("final group profile pic =>", groupProfileFinalPic());
// Önce grubu yaratalım..
// eslint-disable-next-line prefer-destructuring
const key = firebase
.database()
.ref()
.child('groups')
.push().key;
firebase
.database()
.ref('/groups/' + key)
.set({
admin: {
email: myUser.email,
name: myUser.name,
uid: myUser.uid,
},
groupName,
groupDescription,
groupProfilePic: groupProfileFinalPic(),
projects: '',
})
.then(() => {
console.log('Groups oluşturuldu.');
})
.catch(e => {
Alert.alert('Hata', 'Beklenmedik bir hata meydana geldi.');
console.log(e.message);
});
dispatch({
type: ADD_PROJECT_GROUP,
});
};
You are not awaiting groupProfileFinalPic(). This should be done before creating the action you want to dispatch.
groupProfileFinalPic().then(groupProfilePic => {
return firebase
.database()
.ref("/groups/" + key)
.set({
admin: {
email: myUser.email,
name: myUser.name,
uid: myUser.uid
},
groupName,
groupDescription,
groupProfilePic,
projects: ""
})
.then(() => {
console.log("Groups oluşturuldu.");
})
.catch(e => {
Alert.alert("Hata", "Beklenmedik bir hata meydana geldi.");
console.log(e.message);
});
});
I have no clue what the last dispatch is for, you might want to do that in one of the callbacks. Your code is to verbose for an SO question, but I hope this helps anyways.
You are using both await and then on the same call. To use await, you can arrange it something like
const uploadImage = async (imageSource, whereToUpload) => {
...
try {
let data = await RNFS.fs.readFile(uploadUri, 'base64')
let uploadBlob = await Blob.build(data, { type: `${mime};BASE64` }))
...etc...
return finalResult
catch (e) {
// handle error
}
}

Resources