Firestore storing partial data to document - reactjs

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

Related

How to assign objects to an array

I am querying data from firebase, I then want to assign the fetch data to be an array
This is my code
let list = [];
dispatch(fetchUsersPending());
db.collection("users").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
list.push({...doc.data()});
console.log('All Users: ', list);
dispatch(fetchUsersSuccess(list));
});
}).catch((error) => {
var errorMessage = error.message;
console.log('Error fetching data', errorMessage);
dispatch(fetchUsersFailed({ errorMessage }));
});;
But in my console am getting an error showing Error fetching data Cannot add property 1, object is not extensible in react firebase
I think your current approach also causes to many unnecessary dispatches to the store. With the following solution you only map your array to documents once and then dispatch them all at once.
With async/await
const fetchData = async () => {
try {
dispatch(fetchUsersPending());
const users = (await db.collection('users').get()).docs.map((doc) => ({ ...doc.data()}));
dispatch(fetchUsersSuccess(users));
} catch (errorMessage) {
dispatch(fetchUsersFailed({ errorMessage }));
}
}
With .then()
const fetchData = () => {
dispatch(fetchUsersPending());
const users = db.collection('users').get().then((snapshot) => {
const users = snapshot.docs.map((doc) => ({ ...doc.data() }));
dispatch(fetchUsersSuccess(users));
}).catch((errorMessage) {
dispatch(fetchUsersFailed({ errorMessage }));
});
}

React/Redux: How to async or something else?

Hello Everyone,
need your help today with filtering in Redux...
I have filter (you can see on a picture) with several inputs (filters) for my search.
In order to receive Fleet information (filter) I need to pass an "ID" form Client...
const clientChange = (event) => {
const client = event.target.value;
const client_id = client.id;
dispatch({ type: "CLIENT_LIST_SELECTION", payload: client_id });
getFleetFilter();
};
That's my function clientChange in Form.js
const client_id = useSelector((state) => state.client.selection);
const getFleetFilter = async () => {
dispatch({ type: "FLEET_LIST_REQUEST" });
try {
let res = await getFleet(token, client_id);
let data = res.data.data
dispatch({ type: "FLEET_LIST_LOAD", payload: data });
} catch (err) {
if (err) {
console.log("Error Fleet Data");
console.log(err);
};
};
};
That's my function getFleetFilter in Search.js
Problem: I have undefined client_id in API string, because, function getFleetFilter getting called quicker, than client_id getting stored in Redux!
Question: How can I avoid this keeping using Redux here ?
Thank you!
You can use the useEffect callback for this like so:
const client_id = useSelector((state) => state.client.selection);
useEffect(() => {
if (client_id) {
getFleetFilter();
}
}, [client_id]);
const clientChange = (event) => {
const client = event.target.value;
const client_id = client.id;
dispatch({ type: "CLIENT_LIST_SELECTION", payload: client_id });
};
const getFleetFilter = async () => {
dispatch({ type: "FLEET_LIST_REQUEST" });
try {
let res = await getFleet(token, client_id);
let data = res.data.data
dispatch({ type: "FLEET_LIST_LOAD", payload: data });
} catch (err) {
if (err) {
console.log("Error Fleet Data");
console.log(err);
};
};
};

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 array not storing last value

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.

Resources