React-Native Firebase Image upload Expo - reactjs

I am trying to upload an image to firebase storage however I am getting the error object Object as shown below
Please may someone help me I have never uploaded an image to firebase and really need assistance . Any help what's so ever will be much appreciated. Thank you sooo much in advance!!!!!
This is my code. I've Initialized firebase as well as my image path postImage works as expected.
const handleSubmit = () => {
if (postImage !== undefined) {
const fileExtention = postImage[0].split('.').pop()
console.log(`EXT ${fileExtention}`)
const fileName = `${uniqid}.${fileExtention} `
const reference = firebase.storage().ref(`Posts/images/${fileName}`)
reference.put(postImage)
.on(
firebase.storage.TaskEvent.STATE_CHANGED,
snapshot => {
console.log(`snapshot ${snapshot.state}`)
console.log(`progress ${(snapshot.bytesTransferred / snapshot.totalBytes) * 100}`)
if (snapshot.state === firebase.storage.TaskState.SUCCESS) {
console.log('Success')
}
},
error => {
unsubscribe()
console.log("image upload failed" + error.toString())
},
() => {
firebase.storage()
.ref(`posts/images/${fileName}`)
.getDownloadURL()
.then((downloadUrl) => {
console.log(`file available at ${downloadUrl}`)
})
}
)
}
}

here a solution
const [image, setImage] = useState(null);
const [uploading, setUploading] = useState('')
useEffect(() => {
getPermission();
}, []);
const getPermission = async () => {
if (Platform.OS !== "web") {
const { status } =
await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== "granted") {
alert("Sorry, we need camera roll permissions to make this work!");
}
}
};
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if (!result.cancelled) {
setImage(result.uri);
}
};
const getPictureBlob = (uri) => {
// https://github.com/expo/expo/issues/2402#issuecomment-443726662
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", image, true);
xhr.send(null);
});
};
const uploadImageToBucket = async () => {
let blob;
try {
setUploading(true);
blob = await getPictureBlob(image);
const ref = await storage.ref().child(uuid.v4());
const snapshot = await ref.put(blob);
return await snapshot.ref.getDownloadURL();
} catch (e) {
alert(e.message);
} finally {
blob.close();
setUploading(false);
}
};

Related

React useEffect gives react-hooks/exhaustive-deps error on publishing

My .net core react web application works fine, except that when I try to publish it gives me the following error:
Occurred while linting C:\.....Fetch.js: 79
Rule: "react-hooks/exhaustive-deps"
This is my code:
const populateTable1Data = async () => {
var response = await axios.get(apiurl + { params: { id: props.id1 } });
var data = await response.data;
setTable1Data(data);
}
const populateTable2Data = async () => {
var response = await axios.get(apiurl + { params: { id: props.id2 } });
var data = await response.data;
setTable2Data(data);
setLoading(false);
}
useEffect(() => {
const load = async () => {
await populateTable1Data();
await populateTable2Data();
setLoading(false)
}
load()
}, []);
Problem is that I have a very similar useEffect inside another component which doesn't give errors though:
const populateTableData = async () => {
const response = await axios.get(apiurl + key);
const data = await response.data;
setTableData(data);
setLoading(false);
}
useEffect(() => {
populateTableData();
}, [])
If anyone has the same problem, I solved by doing this:
const populateTable1Data = async (dataProps) => {
var response = await axios.get(apiurl + { params: { id: dataProps.id1 } });
var data = await response.data;
setTable1Data(data);
}
const populateTable2Data = async (dataProps) => {
var response = await axios.get(apiurl + { params: { id: dataProps.id2 } });
var data = await response.data;
setTable2Data(data);
setLoading(false);
}
useEffect(() => {
const load = async () => {
await populateTable1Data(props);
await populateTable2Data(props);
setLoading(false)
}
load()
}, [props]);
I essentially passed the props on the function call, I don't know why does it have to be this way, I'll leave the answer here in case anyone else needs it while waiting for someone to be kind enought to explain the reason for this.

How does infinite scroll work in case of caching redis

In case of no cache, infinite scroll works, but when you add cache code, the data repeats when pagination is finished. how can i solve. I am doing a clone project. I'm new to redis, I'd be very grateful if you could reply. I can't think of anything about it (:
Backend my code
const searchpost = async (req, res) => {
let perpage = 3;
const value = req.query.q;
const pageNumber = req.query.page;
try {
const redisPosts = await client.keys("Blog*");
if (redisPosts.length > 0) {
async.map(
redisPosts,
async function (redisPost) {
const cacheBlog = await client.get(redisPost);
let parseData = JSON.parse(cacheBlog);
let job = { ...parseData };
return job;
},
function (err, results) {
if (err) throw err;
res.status(200).json({ searcharticles: results });
}
);
} else {
const searcharticles = await Blog.find({
$or: [
{ title: { $regex: value, $options: "i" } },
{ tag: { $regex: value, $options: "i" } },
{ Subtitle: { $regex: value, $options: "i" } },
],
})
.skip((pageNumber - 1) * perpage)
.limit(perpage)
.populate("authorId");
async.map(
searcharticles,
async function (searcharticle) {
let cacheKey = `Blog:` + uuidv4();
await client.set(cacheKey, JSON.stringify(searcharticle));
return searcharticles;
},
function (err, searcharticles) {
if (err) throw err;
res.status(200).json({ searcharticles });
}
);
}
} catch (err) {
res.status(401).json({ message: "hata durumu oluştu" });
}
};
infinity scroll react code
export const SearchPost = (query, pageNumber) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const [blogs, setBlogs] = useState([]);
const [hasMore, setHasMore] = useState(false);
const [userInfo, setuserInfo] = useState();
useEffect(() => {
setBlogs([]);
}, [query]);
useEffect(() => {
setLoading(true);
setError(false);
let cancel;
axios({
method: "GET",
url: `/api/search`,
params: { q: query, page: pageNumber },
withCredentials: true,
cancelToken: new axios.CancelToken((c) => (cancel = c)),
})
.then((res) => {
console.log(res.data);
setBlogs((prevBlog) => {
return [
...new Set([...prevBlog, ...res.data.searcharticles.map((b) => b)]),
];
});
setHasMore(res.data.searcharticles.length);
setLoading(false);
setuserInfo(res.data.userInfo);
})
.catch((err) => {
if (axios.isCancel(err)) return;
setError(true);
});
return () => cancel();
}, [query, pageNumber]);
return { loading, error, blogs, hasMore, userInfo };
};
const [query, setQuery] = useState("");
const [pageNumber, setPageNumber] = useState(1);
const { ısAuthenticated } = useContext(AuthContext);
const { blogs, hasMore, loading } = SearchPost(query, pageNumber);
const observer = useRef();
const lastBlogElementRef = useCallback(
(node) => {
if (loading) return;
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
//burda verıyı gecıp gecmedıgını kontrol etmelıyız
setPageNumber((prevPageNumber) => prevPageNumber + 1);
}
});
if (node) observer.current.observe(node);
},
[loading, hasMore]
);
function handleSearch(e) {
setQuery(e.target.value);
setPageNumber(1);
}
I'm writing for those who encounter this problem, you don't need to do a for loop. You can do this by typing the number of pages into the key. The edited code is below.
const searchpost = async (req, res) => {
let perpage = 3;
const value = req.query.q;
const pageNumber = req.query.page;
const query = `Blog:` + "/" + pageNumber;
try {
let redisPosts = await client.get(query);
if (redisPosts) {
redisPosts = JSON.parse(redisPosts);
res.status(200).json({ searcharticles: redisPosts });
} else {
const searcharticles = await Blog.find({
$or: [
{ title: { $regex: value, $options: "i" } },
{ tag: { $regex: value, $options: "i" } },
{ Subtitle: { $regex: value, $options: "i" } },
],
})
.skip((pageNumber - 1) * perpage)
.limit(perpage)
.populate("authorId");
let cacheKey = query;
await client.set(cacheKey, JSON.stringify(searcharticles));
res.status(200).json({ searcharticles });
}
} catch (err) {
res.status(401).json({ message: "hata durumu oluştu" });
}
};

waiting array of urls after uploading images to firebase storage and then stroing it again to firestore

const sendImageToFirebase = (e) => {
const promises = []
const urlsArray = []
// productimage is an array of image files
productImage.forEach((image, i) => {
var storageRef = firebase.storage().ref();
var uploadTask = storageRef.child(`${userDetailsFirebase.uid}/` + Math.random()).put(image);
promises.push(uploadTask.on('state_changed',
(snapshot) => {
},
(error) => {
console.log("error");
},
async () => {
const downloadurl = await uploadTask.snapshot.ref.getDownloadURL()
urlsArray.push(downloadurl)
}
))
})
Promise.all(promises).then(res => {
db.collection("products").doc(idGeneratedforProduct).set(
{
imageURL: urlsArray, //array of image urls
},
).then(e => {
}).catch(error => console.log("Error while sendig items to Firebase"))
})
}
I want to upload a multiple images to firebase storage. Here, sendImagToFirebase is a normal function in reactJs, and productimage is an array of image files. I want to wait for URL for each image files and then store all of them as an array to firestore. I would appreciate your input on how to do it?
You can create a function that receoves the ref and the file and returns the downloadURL. By calling it for each file with a Promise.all you get as result your array of downloadURLs:
const uploadFileAndGetDownloadURL = async (ref, file) => {
const snap = await ref.put(file);
const downloadURL = await snap.ref.getDownloadURL();
return downloadURL;
};
const sendImageToFirebase = async (e) => {
const promises = [];
productImage.forEach((image, i) => {
var storageRef = firebase.storage().ref();
var ref = storageRef.child(`${userDetailsFirebase.uid}/` + Math.random());
promises.push(uploadFileAndGetDownloadURL(ref, image));
});
//Your array with the urls
const urlsArray = await Promise.all(promises);
};

Having issues uploading an image file to firebase using React-native/Expo

Been trying to upload an image to firebase storage but haven't had any luck thus far. So when I pick an image from the library it displays it but after I try on pressing the post button it just gives me an error.
Here's the error I get: https://imgur.com/a/KLSeu34
export default PostScreen = () => {
const [image, setImage] = useState(null);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3],
width: 300,
height: 400,
quality: 1,
});
if (!result.cancelled) {
console.log("user cancelled image");
setImage(result.uri);
}
};
const submitPost = async () => {
const result = await uploadImage();
console.log("Image Url: ", imageUrl);
};
const uploadImage = async (uri, imageName) => {
const response = await fetch(uri);
const blob = await response.blob();
var ref = firebase
.storage()
.ref()
.child("images/" + imageName);
return ref.put(blob);
};

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