Updating profile picture in firebase - reactjs

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);
}, []);

Related

Socket works the for a few seconds then fails

I've managed to establish a connection using socket. It works great for the first few seconds after that it runs super slow takes like almost 2-3 mins to complete a request. And then it produces this error continuously. The app doesn't crash it just runs slowly with the error displaying countless times.
Firefox can’t establish a connection to the server at ws://localhost:5000/socket.io/?EIO=4&transport=websocket&sid=9S6kqHJdHHXQgrobAAHp..
Error on console.
Main.js
function Home(props) {
const [Username , setUsername] = useState("")
const [SearchedData, setSearchedData] = useState()
const [Data, setData] = useState()
const socket = io('http://localhost:5000')
React.useEffect(() => {
// socket.current = io('http://localhost:5000')
socket.emit("content","yada")
socket.on("get-data", data => {
setData(data)
})
})
function NavBar(props){
const handleClick = (e) => {
const {id} = e.target
if(id === "Post-btn"){
if(Content.length > 0){
let data = {
Username: "yada", Content
}
props.socket.emit("store-data", data)
}
}
return(
Tags....
)}
function Content (props) {
const onLike = (e) => {
const { id } = e.target.dataset
const data = {
username: "yada",
id : id
}
// console.log(data)
props.socket.emit("like", data)
}
return(
Tags.....
)
}
server.js
mongoose.connect(process.env.MongoDB,
{ useNewUrlParser: true, useUnifiedTopology: true }).then(() => {
console.log("Database Connected")
}).catch(err => {
console.log(err)
});
const server = app.listen(process.env.Port, () => {
console.log("Connected on " + process.env.Port)
})
const io = socket(server, {
cors:{
origin: "http://localhost:3000",
credential: true,
}
})
let cuid;
io.on("connection", (socket) => {
socket.on("content", username => {
Comments.find({},(err, data) => {
if(!err)
socket.emit("get-data", data)
})
})
socket.on("store-data", data => {
const {Username, Content} = data
const newdata = new Comments({
userName: Username,
content: Content,
createdAt: new Date().toDateString(),
replies: []
})
newdata.save().then(data => {
for(const d in data)
if(d === "_id"){
Users.findOneAndUpdate({username: Username}, {$push: {UserContent: data[d]}}, {new: true}, (err, save) => {
if(err)
console.log(err)
else
console.log(save)
})
}
})
})
socket.on("like", data => {
const {username, id} = data
Users.findOne({username:username}, (err, data) => {
if(!err){
cuid = data['id']
console.log(cuid)
Comments.findByIdAndUpdate(id, {$set: {score: data['_id']}}, {upsert: true}, (err, d) => {
if(!err){
console.log(d)
}
})
}
})
})
})
Looking at the code provided, I noticed there is an useEffect without params. This may be causing a loop until the application crashes.
React.useEffect(() => {
// socket.current = io('http://localhost:5000')
socket.emit("content","yada")
socket.on("get-data", data => {
setData(data)
})
socket.on("Updated", data => {
setData(data)
})
}, []); <- this is missing
This empty array indicates that the content inside the useEffect will only run once.
More about this https://reactjs.org/docs/hooks-intro.html

Calling axios request one after the other?

I have tow functions in my ReactJs application called,
AuthService.addUser(newUser);
AuthService.userCategories(usercategories);
I want to run these two functions separately, which means the Axios request of the second function should be called after the Axios request of the first function when clicked the submit button. How do I approach the solution? Thanks in advance.
I tried in this way. Is this correct?
const handleSubmit = (e) => {
e.preventDefault();
AuthService.addUser(newUser);
AuthService.userCategories(usercategories);
};
Here are my two functions
addUser: (user) => {
//console.log(post);
axios
.post(CONSTANTS.HOSTNAME + "/api/users/register", user)
.then((res) => {
//save to local storage
const { token } = res.data;
localStorage.setItem("jwtToken", token);
isAuthenticated.next(true);
setAuthToken(token);
Swal.fire({
icon: "success",
title: "Signup Successful!",
showConfirmButton: false,
timer: 1500,
}).then(() => {
window.location.href = "/";
//decode token to get user data
const decoded = jwt_decode(token);
currentUser.next(decoded);
console.log(decoded);
});
})
.catch((err) => {
console.log(err.response.data);
Swal.fire({
icon: "error",
title: "Oops...",
text: err.response.data,
});
// alert(JSON.stringify(err.response.data));
});
},
userCategories: (userCategories) => {
axios
.post(CONSTANTS.HOSTNAME + "/api/users/usercategories", userCategories)
.then((res) => {
console.log(res.data);
});
},
just use promise if function return promise:
const handleSubmit = async (e) => {
e.preventDefault();
await AuthService.addUser();
await AuthService.userCategories();
};
or make promise from function and run async
function one() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('resolve one')
return resolve("i am after five seconds")
},
2000);
});
}
function two() {
return new Promise((resolve, reject) => {
console.log('resolve two')
return resolve("i am after three seconds")
});
}
const handleSubmit = async () => {
console.log('run handleSubmit')
await one();
await two();
}
handleSubmit()

Sign up form data is not storing on firebase except the image

I'm trying to create sign up form in react-native using Firebase.I've used Fetch Blob and Document Picker libraries for getting image and upload it to firebase. And I'm also trying to save the user's name, email, and password in realtime database. But unfortunately, the user data is not going to save in database except the image is uploaded in the firebase storage.
Here is my Firebase Auth Code
handleSignupOnPress = () => {
const {image, email, password} = this.state;
let validation = this.validateData();
console.warn(validation);
if (validation == true) {
this.toggleLoading();
firebaseService
.auth()
.createUserWithEmailAndPassword(email, password)
.then(() => {
// console.warn("User SignUp Successfully");
this.uploadImage(image);
})
.catch(error => {
this.toggleLoading();
var errorCode = error.code;
var errorMessage = error.message;
alert(errorMessage);
// console.warn("ERROR => ", errorCode, errorMessage);
});
}
};
Here is image Upload Code
// First Uploading image and download Image URI then call saveUserToDB()...
uploadImage(uri, mime = 'image/jpeg') {
return new Promise((resolve, reject) => {
const uploadUri =
Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
let uploadBlob = '';
const imageRef = firebaseService
.storage()
.ref('images')
.child(uuid.v4());
fs.readFile(uploadUri, 'base64')
.then(data => {
return Blob.build(data, {type: `${mime};BASE64`});
})
.then(blob => {
uploadBlob = blob;
return imageRef.put(blob, {contentType: mime});
})
.then(() => {
uploadBlob.close();
const downnloadImageURI = imageRef.getDownloadURL().then(url => {
this.setState(
{
imageURI: url,
},
() => {
alert('ImageURI ==> ', this.state.imageURI);
this.saveUserInfo();
},
);
});
return downnloadImageURI;
})
.then(url => {
resolve(url);
})
.catch(error => {
this.toggleLoading();
reject(error);
});
});
}
Here is code for saving user's data
saveUserInfo = () => {
const {userName, email, password, imageURI} = this.state;
const {navigate} = this.props.navigation;
const uid = firebaseService.auth().currentUser.uid;
const params = {
image: imageURI,
username: userName,
email: email,
password: password,
};
//firebaseService.database().ref('/Users').push(params)
firebaseService
.database()
.ref('/Users')
.child(uid)
.set(params)
.then(res => {
this.toggleLoading();
navigate('Login');
})
.catch(err => {
alert(err);
});
};
Here are screenshots of Firebase Console
Are the "Rules" in database given permission to "Write"
Go to the firebase console and open your project.
Go to the database and search for "Rules" tab.
Check the rules are set as below
{
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
"rules": {
".read": true,
".write": true
}
}
I've solved this issue. The issue was in this piece of code.
const downnloadImageURI = imageRef.getDownloadURL().then(url => {
this.setState(
{
imageURI: url,
},
() => {
alert('ImageURI ==> ', this.state.imageURI);
this.saveUserInfo();
},
);
setState was not working and calback was not fired.
And I've made it like this way
const downnloadImageURI = imageRef.getDownloadURL().then(url => {
this.saveUserInfo(url)
);}

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