How to retrieve image from firebase in react native expo? - javascript

I am new to React Native and still learning by doing. I have uploaded images in firebase which I want to show on the second screen. Although, I keep getting errors like
can't find variable: profileImageUrl
I am trying to retrieve the image on the next page.
Here is the code for uploading to firebase:
const uploadImage = async () => {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.oneerror = function () {
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', image, true);
xhr.send(null);
});
const ref = firebase.storage().ref().child('/ankit/');
const snapshot = ref.put(blob);
snapshot.on(
firebase.storage.TaskEvent.STATE_CHANGED,
() => {
setUploading(true);
},
(error) => {
setUploading(false);
console.log(error);
blob.close();
},
() => {
snapshot.snapshot.ref.getDownloadURL().then((url) => {
setUploading(false);
console.log('downlaod url', url);
return url;
});
}
);
};
And here is the code for retrieving:
const [Image, setImage] = useState(false);
let imageRef = firebase.storage().ref('/ankit/');
imageRef
.getDownloadURL()
.then((url) => {
setImage({ profileimageUrl: 'url' });
})
.catch((e) => console.log('getting downloadURL of image error => ', e));
return (
<View>
<Image source={this.state.profileImageUrl}></Image>
</View>
)

You should refactor the code that shows the image. You are using the new hooks state to store the state but try to use it in the html with the syntax of the old react state syntax. This is how it should be:
const [image, setImage] = useState(false);
useEffect(() => {
let imageRef = firebase.storage().ref('/ankit/');
imageRef
.getDownloadURL()
.then((url) => {
setImage(url);
})
.catch((e) => console.log('getting downloadURL of image error => ', e));
},[])
return (
<View>
<Image src={image}></Image>
</View>
);

Related

Convert fetch to axios

I did a 'get' with fetch but I want to do it with axios, could someone help me convert this code to axios?
detail: detail: I made the request to get an image, and I use the blob to be able to show this image to the user, and I would like to do that with axios as well.
Code:
const image = (url) =>
fetch(url)
.then((response) => {
return response.blob();
})
.then(
(blob) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
})
);
const image = async (url) =>
await axios.get(url)
.then(response => {
// can access blog directly from response...
}
Read more about axios here
Here: I am assuming this is a get request?
const image = async (url) => {
return await axios.get(url)
.then((response) => {
return response.blob();
})
.then(
(blob) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
})
);
}

Using compressorjs with React Native expo

I'm trying to using the amazing compressorjs library in my React native expo project.
Currently, I have this:
import Compressor from 'compressorjs';
export const uploadPicture = async (uri, path) => {
const blob = await 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", uri, true);
xhr.send(null);
});
new Compressor(blob, { //<--- Problem
quality: 0.6,
maxWidth: 512,
maxHeight: 512,
success(result) {
console.log(result)
},
error(err) {
console.log(err.message)
}
})
blob.close();
//firebase stuff to upload after...
}
I'm assuming this doesn't work because compressorjs only allows File and Blob types and I'm inserting a Promise instead. But I have no clue what to do instead.
If anyone can point me into the right direction, that would be amazing!
Thanks.
Consider using the fetch API response.blob method to get the image blob from the URI as opposed to using Ajax XMLHttpRequest
Like this -
Getting the blob via the URI
let blob = await fetch(uri).then(r => r.blob());
You can also take it a step further by getting the actual file from the blob, like this:
Getting the image file from the blob
let file = await fetch(url)
.then((r) => r.blob())
.then((blobFile) => new File([blobFile], "fileName", { type: "image/png" }));
Your finished code should look something like:
import Compressor from "compressorjs";
export const uploadPicture = async (uri, path) => {
let blob = await fetch(uri).then(r => r.blob());
new Compressor(blob, {
...
});
};
OR this
import Compressor from "compressorjs";
export const uploadPicture = async (uri, path) => {
let file = await fetch(url)
.then((r) => r.blob())
.then((blobFile) =>
new File(
[blobFile],
"fileName",
{ type: "image/png" })
);
new Compressor(file, {
...
});
};
Disclaimer
Please note that there's no guarantee that this suggestion will definitely solve your problem but it's DEFINITELY worth a shot.
Cheers.

How to await the result from an async function? [duplicate]

This question already has answers here:
How to "await" for a callback to return?
(5 answers)
Closed 1 year ago.
I'm currently working with Firebase to upload an image to the storage.
I created an uploadImage function which takes an image and saves it to Firebase Storage then returns the url of that saved image. When the user clicks the Submit button, I use that uploadImage function to save that image and get back a url. The image is properly being saved, but the url that is being logged is undefined. I'm pretty sure it's an issue with the aysnc-await implementation I have. Any thoughts on this? Thank you!
UploadForm.js:
import { uploadImage } from "../firebase/functions";
const UploadForm = () => {
const [image1, setImage1] = useState(null);
const saveForm = async (file) => {
const url1 = await uploadImage(image1);
console.log("URL", url1); //the url here is UNDEFINED
};
return (
<ImageUploadForm setImageProp={setImage1} />
<button
onClick={(e) => {
e.preventDefault();
saveForm(image1);
}}
></button>
);
uploadImage function:
const uploadImage = async (file) => {
const storageRef = storageService.ref().child("posts/" + file.name);
storageRef.put(file).on(
"state_changed",
(snapshot) => {},
(error) => {
console.log(error);
},
async () => {
return await storageRef.getDownloadURL();
}
);
};
Your uploadImage function doesn't return anything, just return the promise
return storageRef.put(file).on(
or, (since I don't know how that function works / what it returns), possibly
const uploadImage = (file) => {
return new Promise((resolve, reject) => {
const storageRef = storageService.ref().child("posts/" + file.name);
storageRef.put(file).on(
"state_changed",
(snapshot) => {},
(error) => {
console.log(error);
reject(error);
},
() => {
const res = storageRef.getDownloadURL();
resolve(res);
}
);
};
}

JS read file onload returns undefined

I want to read a TXT file from a directory, I have this code which works fine
window.onload = () => {
fetch("file.txt")
.then(res => res.text())
.then(data => {
console.log(data);
});
};
But I want to exe the fetch call in a function like so:
window.onload = () => {
const filePath = "file.txt";
const fileData = readDataFile(filePath);
console.log(fileData);
};
const readDataFile = path => {
fetch(path)
.then(res => res.text())
.then(data => {
return data;
});
};
But in this case, it returns undefined.
Another problem with it, is I can't catch if an error occurs, I tried adding catch to the promise and throw an error but it does not work. This is what I've tried:
window.onload = () => {
fetch("file.txt")
.then(res => res.text())
.then(data => {
console.log(data);
})
.catch(err => {
throw new Error("ERROR!");
});
};
THANKS :)
This works:
const readDataFile = async path => {
try {
const response = await fetch(path);
const data = await response.text();
return data;
} catch (err) {
console.log('Cannot read file.');
}
}
window.onload = async () => {
const filePath = 'data.txt';
const fileData = await readDataFile(filePath);
console.log(fileData);
}
But again, the catch method does not work ? am I doing it wrong ?

how to EventSource with Redux Observable

The question is simple, how can i use redux-observable with an EventSource?
With RxJs its like:
const observable = Observable.create(observer => {
const eventSource = new EventSource('/model-observable');
return () => {
eventSource.close();
};
});
observable.subscribe({
next: data => {
this.zone.run(() => this.someStrings.push(data));
},
error: err => console.error('something wrong occurred: ' + err)
});
This sounds more like a general RxJS question about how to connect to an EventSource. This can be done in a number of ways. If all you care about are the messages (and not errors/open):
import { fromEvent } from 'rxjs/observable/fromEvent';
const fromEventSource = url => {
return new Observable(observer => {
const source = new EventSource(url);
const message$ = fromEvent(source, 'message');
const subscription = message$.subscribe(observer);
return () => {
subscription.unsubscribe();
source.close();
};
});
};
If you care about open and/or errors, it requires a little more code to pipe everything together:
import { Observable } from 'rxjs/Observable';
import { Subscriber } from 'rxjs/Subscriber';
const fromEventSource = (url, openObserver) => {
return new Observable(observer => {
const open = new Subscriber(openObserver);
const source = new EventSource(url);
const onOpen = event => {
open.next(event);
open.complete();
};
const onError = event => {
if (event.readyState === EventSource.CLOSED) {
observer.complete();
} else {
observer.error(event);
}
};
const onMessage = event => {
observer.next(event.data);
};
source.addEventListener('open', onOpen, false);
source.addEventListener('error', onError, false);
source.addEventListener('message', onMessage, false);
return () => {
source.removeEventListener('open', onOpen, false);
source.removeEventListener('error', onError, false);
source.removeEventListener('message', onMessage, false);
source.close();
};
});
};
fromEventSource('http://some-url.com')
.subscribe(value => console.log(value));
Usage in redux-observable would be something like this:
const somethingEpic = action$ =>
action$.ofType(SOMETHING)
.mergeMap(() =>
fromEventSource('http://some-url.com')
.map(message => ({
type: MESSAGE,
payload: message
}))
.catch(e => Observable.of({
type: SOMETHING_ERROR,
payload: e,
error: true
}))
);

Categories