firestore array not storing last value - reactjs

I have a Registration form which has many fields for submission.Form submission is working fine, saving all the details to firestore. I have input file upload, user can select multiple files, on submit, uploadin all the files to firebase storage ans saving the upload link in an array(FileURLs).
For Example if I have selected 3 files on submit when i do console.log of state I can see the FileURLs with 3 data but In firestore last value is not getting saved.
Code
handleSubmit = (e) => {
e.preventDefault();
const promises = [];
const {fileURLs,sp_License}=this.state;
let files=[];
let orgFile='';
let err = this.validate();
if (!err) {
this.setState({ loading: true,disChecked:false })
// this.fileupload();
// this.MultifileuploadHandler();
const Lfilename = this.state.sp_Name + '_' + new Date().getTime();
const uploadTask = storage.ref('License/' + Lfilename).put(sp_License);
promises.push(uploadTask);
uploadTask
.then(uploadTaskSnapshot => {
return uploadTaskSnapshot.ref.getDownloadURL();
})
.then(url => {
// orgFile.push({url});
// this.setState({sp_License:url})
orgFile=url
// console.log(orgFile)
},()=>{
console.log(sp_License)
});
//multi pilots file
const storageRef = storage.ref();
this.state.sp_PilotsLicense.forEach((file) => {
const uploadTask= storageRef
.child(`License/${file.name}`).put(file)
promises.push(uploadTask);
uploadTask.then((snapshot) => {
return snapshot.ref.getDownloadURL();
}).then(url =>{
files.push({url});
})
});
Promise.all(promises).then(tasks => {
console.log('all uploads complete');
console.log(this.state)
if(this._mounted)
{
console.log(orgFile)
this.setState({
fileURLs: files,
sp_License:orgFile,
},()=>{
console.log(this.state)
});
}
this.saveData();
});
}
}
saveData=()=>{
let uid = this.props.auth.uid;
let keysToRemove = ["loading", "checked", "disChecked", "open", "message"]
let newState = Object.entries({...this.state}).reduce((obj, [key, value]) => {
if(!keysToRemove.includes(key)){
obj[key] = value
}
return obj
}, {})
console.log(newState)
this.props.UpdateUserDetails(uid, newState,this.successMessage)
}
Action
export const UpdateUserDetails= (id, droneSPDetails,func) => {
console.log(droneSPDetails)
console.log(func)
return (dispatch, getState, { getFirestore }) => {
const firestore = getFirestore()
firestore.collection('users')
.doc(id)
.set({
...droneSPDetails,
sp_RegisteredOn: new Date(),
sp_Status:"pending",
sp_ActiveFlag:"1",
},{ merge: true })
.then(() => {
func();
dispatch({ type: 'CREATE_DRONESP', droneSPDetails });
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
}
This is the value passed to store on firestore (from console.log)
fileURLs: Array(3)
0: {url: "https://firebasestorage.googleapis.com/v0/b/dronew…=media&token=084bc59a-8087-43de-afdb-05d4192ec4d2"}
1: {url: "https://firebasestorage.googleapis.com/v0/b/dronew…=media&token=3d427621-6a8b-4ed7-b6ce-5c3940fe7ee6"}
2: {url: "https://firebasestorage.googleapis.com/v0/b/dronew…=media&token=e24a5bab-e584-4a95-bb70-4d6c9f7fed7c"}
length: 3
but I can see only these 2 values getting saved.

Related

Updating profile picture in firebase

i'm not sure what i'm doing wrong here, i upload a new picture to firebase storage, then i retrieve it with getDownloadUrl, and then i update the user profile photoURL, but for some reason it's not working.
const imgPath = ref(storage, "images/");
const imgUpload = () => {
if (uImg == null) return;
const imgRef = ref(storage, `images/${uImg.name + v4()}`);
uploadBytes(imgRef, uImg).then(() => {
listAll(imgPath).then((response) => {
response.items.forEach((item) => {
getDownloadURL(item).then((url) => {
setImgUrl([url]);
updateProfile(auth.currentUser, {
photoURL: `${imgUrl[0]}`,
})
.then(() => {
setProfileImg(auth.currentUser.photoURL);
console.log("success");
})
.catch((error) => {
console.log(error);
});
});
});
});
});
};
uImg is the uploaded img
It is unlikely the current user is updated by the time the updateProfile then statement runs.
Instead update the useState hook as with the imgUrl[0].
updateProfile(auth.currentUser, { photoURL: `${imgUrl[0]}` })
.then(() => {
setProfileImg(imgUrl[0]);
console.log("success");
}).catch((error) => { console.log(error); });
If you want to verify that the profile image was updated print of the value:
const auth = getAuth();
useEffect(() => {
console.log("Profile:", auth.currentUser?.photoURL);
}, []);

Unable to add array to firebase-firestore in reactjs?

I am trying to send a list of arrays to Firestore using a variable called array_list but when I check my firebase console the array is present but the value inside of it is empty.
let array_list = [];
let user_id = localStorage.getItem("userId");
function add_data() {
let i = 0;
for(i;i<10;i++){
array_list.push(i);
}
}
add_data()
let db = firebase.firestore();
if (user_id !== null) {
var doc = db.collection("users").doc(user_id);
}
const sendHistData = () => {
console.log("Creating Database...");
doc
.set({
browsingHistory: array_list,
})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.log(error);
});
};
if(user_id!==null){
add_data();
sendHistData();
}
Here is the link to the full code
Here is the screenshot
The var "doc" seems to be undefined in your sendHistData function. Try refactoring the function:
let db = firebase.firestore();
const sendHistData = () => {
// if (!user_id) return null // user not logged in
const db = firebase.firestore().collection("users").doc(user_id)
console.log("Creating Database...");
doc
.set({
browsingHistory: array_list,
})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.log(error);
});
};
Also you are checking if user_id is null or not before calling the function so verifying that again inside of the function is redundant.

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
}
}

Firestore storing partial data to document

I have a issue with data saving to Firestore. I'm passing a list of url's to be saved to the document.
data sent in the following format
But it saving only the first data
firestore data
what may be issue? Please help.
update button click handler
handleUpdate=()=>{
const promises = [];
let files=[];
const {fileURLs,sp_License,sp_PilotsLicense}=this.state;
let err = this.validate();
if (!err) {
this.setState({ loading: true,disChecked:false })
// const Lfilename = this.state.sp_Name + '_' + new Date().getTime();
// const uploadTask = storage.ref('License/' + Lfilename).put(sp_License);
let orgFile='';
const promise1=this.uploadTaskPromise().then((res)=>{
console.log(res)
orgFile=res
});
promises.push(promise1)
console.log(orgFile)
//promises.push(this.uploadTaskPromiseMulti());
const promise2=this.uploadTaskPromiseMulti().then((res)=>{
console.log(res)
files=res
});
promises.push(promise2)
console.log(promise2)
Promise.all(promises).then(tasks => {
console.log('all uploads complete');
console.log(this.state)
if(this._mounted)
{
//this.saveData();
//console.log(orgFile.data)
this.setState({
fileURLs: files, -- here fileurls gets updated
sp_License:orgFile,
},()=>{
console.log(this.state)
this.saveData();
});
}
});
}
}
code of saveData method - I'm using react redux firebase method for saving data
saveData=()=>{
let uid = this.props.auth.uid;
let keysToRemove = ["loading", "checked", "disChecked", "open", "message",
"sp_NameError", "sp_PhoneError", "sp_emailError", 'usr_org_LicenseNumberError',
'sp_LicenseError','usr_org_StateConveredError','usr_org_DistConveredError',
'sp_NumberofEquipmentsError','sp_NumberofDronePilotsError','sp_PilotsLicense',
'sp_NumberofEquipmentsOwnedError','sp_ToolError','processingToolServiceError',
'processingToolDomainError','modalopen','EquipmentCount',
'PilotsCount','buttonName','isReady','redirect']
let newState = Object.entries({...this.state}).reduce((obj, [key, value]) => {
if(!keysToRemove.includes(key)){
obj[key] = value
}
return obj
}, {})
console.log(newState)
this.props.UpdateUserDetails(uid, newState,this.successMessage)
}
Action code
export const UpdateUserDetails= (id, droneSPDetails,func) => {
return (dispatch, getState, { getFirestore }) => {
const firestore = getFirestore()
firestore.collection('web_Users')
.doc(id)
.set({
...droneSPDetails,
sp_UpdatedOn: new Date(),
//sp_Status:"pending",
sp_ActiveFlag:"1",
},{ merge: true })
.then(() => {
func();
dispatch({ type: 'CREATE_DRONESP', droneSPDetails });
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
}

React - within function setstate not updating state

I have a Service inclusion form, which includes 2 file uploads, one for single file selector and one more for multiple file selector. On submit click calling a function to upload the files to firebase storage and saving the links.
I'm updating the 'fileURLs' and 'sp_License' state in MultifileuploadHandler method. But it is not updating the state. when I do console.log of newState I cannot see the updated states.
Received follwoing error on submit
'FirebaseError: Function DocumentReference.set() called with invalid data. Unsupported field value: a custom File object (found in field sp_License)'
any help appreciated.!
EDIT :-
I have updated my code.
On submit, before uploading the file,save data method is called. How can I wait till upload is done and then call SaveData Method?
handleSubmit = (e) => {
e.preventDefault();
let err = this.validate();
if (!err) {
this.setState({ loading: true,disChecked:false })
this.fileupload();
this.MultifileuploadHandler();
this.saveData();
}
}
saveData=()=>{
let uid = this.props.auth.uid;
let keysToRemove = ["loading", "checked", "disChecked", "open", "message"]
let newState = Object.entries({...this.state}).reduce((obj, [key, value]) => {
if(!keysToRemove.includes(key)){
obj[key] = value
}
return obj
}, {})
console.log(newState)
this.props.UpdateUserDetails(uid, newState,this.successMessage)
}
fileupload=()=>{
//single org file
const {fileURLs,sp_License}=this.state;
const Lfilename = this.state.sp_Name + '_' + new Date().getTime();
const uploadTask = storage.ref('License/' + Lfilename).put(sp_License);
uploadTask
.then(uploadTaskSnapshot => {
return uploadTaskSnapshot.ref.getDownloadURL();
})
.then(url => {
// orgFile.push({url});
this.setState({sp_License:url})
// orgFile=url
// console.log(orgFile)
},()=>{
console.log(sp_License)
});
}
MultifileuploadHandler = () => {
const {fileURLs,sp_License}=this.state;
let files=[];
var orgFile=[];
//multi pilots file
const storageRef = storage.ref();
this.state.sp_PilotsLicense.forEach((file) => {
storageRef
.child(`License/${file.name}`)
.put(file).then((snapshot) => {
return snapshot.ref.getDownloadURL();
}).then(url =>{
files.push({url});
console.log(url)
if(files.length===this.state.sp_PilotsLicense.length)
{
console.log('url')
this.setState({ fileURLs: files },()=>{
console.log(fileURLs)
});
}
})
});
}

Resources