I use google cloud storage in my react project.
I am interested how to set another info of image to the object? for example: name, id etc.
before your advaces, I've used firebase firstore for img infos and after getting datas, creating one full object includes cloud files and firestore infos. BUT...
when I am getting files data in useEffect and want to set him info i have some undefined find item.
firstly when I render page, console parsedGallery returns array of objects.
console.log(item.name) returns item.name
console.log(obg) returns undefined !!!
when one more time refresh page everything getting ok
why happens this? what a problem?
please help me to correct this code or advice me new better way to get from cloud with clean code.
const listRef = ref(storage, `image/${currentUser?.uid}/gallery/`);
const galleryListFirestore = useSelector((state) => state.storeMain.gallery);
let parsedGallery;
if (galleryListFirestore?.length > 0) {
parsedGallery = JSON.parse(galleryListFirestore);
}
console.log(parsedGallery);
const [gallery, setGallery] = React.useState([]);
React.useEffect(() => {
listAll(listRef).then((response) => {
let galleria = [];
response?.items.forEach((item) => {
const obj = parsedGallery?.find((it) => it?.id == item?.name);
console.log(item.name);
console.log(obj);
getDownloadURL(item).then((url) => {
setGallery((prev) => [
...prev,
{
url: url,
id: obj?.id,
name: obj?.name,
uploadTime: obj?.addTime.seconds,
likes: obj?.likes,
post: obj?.post,
},
]);
});
});
setGallery(galleria);
});
}, []);
Related
I'm trying to create a React Native messaging app with the firebase SDK. In the chat screen I am trying to listen to updated messages in my firestore database. I'm following a lot of the code shown in this github repository https://github.com/ReactNativeSchool/react-native-firebase-chat-app, but it uses react-native-firebase and I am using the SDK which is causing making it hard for me to find the equivalent code with the firebase SDK. What am I doing wrong in the below code that is giving me the following error when I open the screen:
undefined is not a function (near '...(0,_firebaseConfig.listenToMessages)(threadID).onSnapshot...')
I believe it has to do with me not converting from react-native-firebase to the firebase SDK correctly, but I'm not sure.
Below is my listenToThreads code from the firebaseConfig file where I do all my firebase functions. Below that is the part I commented out that returned the values within that collection.
export const listenToMessages = async (threadID) => {
return firebase.firestore()
.collection('threads')
.doc(threadID)
.collection('messages');
// try {
// const q = query(collection(db, "threads"), where("tid", "==", threadID));
// const doc = await getDocs(q);
// const data = doc.docs[0].data();
// return data.messages;
// } catch {
// return [];
// }
};
and here is my onSnapshot code which I'm running inside a working UseFocusEffect hook.
const unsubscribe = listenToMessages(threadID).onSnapshot(
querySnapshot => {
const formattedMessages = querySnapshot.docs.map(doc => {
return {
_id: doc.id,
text: '',
createdAt: new Date().getTime(),
user: {}
};
});
setMessages(formattedMessages);
},
);
return () => {
unsubscribe();
};
The listenToMessages function should not be async.
It returns a promise rather than the doc you want. ✌️
Im building a simple event-page where you can create events and buy tickets for those events. I have all the event ids a user has created stored in a firebase firestore doc to access it i need the current logged in users uid. (thats why im pulling the data client-side, no getStaticProps, ... possible) after i get the created events from the user i search with those ids in my event-collection in firestore to get the data i need.
It seems that i cant access a single array-field. array[0] e.g. is displayed as undefined even though in the next moment I get the data loged on the console for the whole array, where array[0] [1] ... is existent.
My basic idea:
get user & uid from fb
get data from firestore with the uid i got
display data with .map
Code:
Variable Declaration:
const auth = getAuth();
const [events, setEvents] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect to get logged in user:
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
getEvents(user.uid);
setIsLoading(false);
}
});
}, []);
get data from firestore:
const getEvents = async (uid) => {
const createdEvents = [];
await getDoc(doc(db, "users", uid)).then((currentUser) => {
currentUser.data().events.forEach(async (eventId) => {
await getDoc(doc(db, "events", eventId)).then((event) => {
createdEvents.push({ ...event.data(), id: event.id });
});
});
setEvents(createdEvents);
});
};
Display data on website:
{isLoading ? (
<span>loading events..</span>
) : (
events.map((event) => {
return <p key={event.id}>{console.log(event.title)}</p>;
})
)}
console outputs:
{isLoading ? null : console.log("event Array: ", events)} {/* data outputs in console */}
{isLoading ? null : console.log("single array element: ", events[0])} {/* is undefined */}
enter image description here
Note: the array renders twice, first time with no data because of the variable declaration (as expected) an second time with data, i just dont know why it wont display on the website.
I appreciate any help, thanks a lot!
I tried moving some variables and changing when the async function fires, nothing helps. Also i tried waiting for the data in the array with events && events.map ...
Is it possible to make a Google Places callback from getDetails function asynchronus or return it's value?
Essentially, in my react app, I am trying to do the following:
pass a placeId to google places api
wait for google to bring back some place information (address, photos, etc)
make a call to my local api to do something with this data from google
What happens though is
google goes to get the data
the call to my api is made but google has not brought back the data yet
I have tried using useState however, the state is not updated right away and thus I am not sure how to "wait" for google places to finish getting data before continuing my call
example of what I am trying to do (obviously wrong)
const [value, setValue] = useState('')
const foo = async (placeId) => {
var service = new window.google.maps.places.PlacesService(
predictionsRef.current,
)
await service.getDetails(
{
placeId,
fields: ['photos'],
},
async place =>
await setValue(
place.photos[0].getUrl({ maxWidth: 1280, maxHeight: 720 }),
),
)
// I want 'value' to have google place data before the axios call
await axios.post(...)
}
I have looked at the following links so far but can't piece together what I need:
google places library without map
https://gabrieleromanato.name/javascript-how-to-use-the-google-maps-api-with-promises-and-async-await
useState set method not reflecting change immediately
You could make it this way,
const [value, setValue] = useState('')
const [placeID, setPlaceID] = useState(null)
a function to return a promise from google placeDetails API,
const getPlaceDetails = (ref) => {
return new Promise(function (resolve, reject) {
let placesService = new window.google.maps.places.PlacesService(ref);
placesService.getDetails(
{
placeId,
fields: ['photos'],
},
(place) => {
resolve(place.something);
}
);
});
};
an effect that triggers upon placeID change
useEffect(() => {
async function doStuff() {
let placesResponse = await getPlaceDetails(ref);
let myResponse = await yourAPICall(placesResponse);
setValue(placesResponse);
}
if(placeID !==null){
doStuff();
}
}, [placeID]);
I haven't tested this code, but hope this approach helps.
I'm trying to retrieve download url so i can pass it down in promise in the function i'm calling.
In the storage image is uploaded but somehow i'm getting error on the line where i console.log - 404 error like it does not exist ( but it does )
uploadFile = (file, metadata) => {
const pathToUpload = this.state.channel.id;
const ref = this.props.messagesRef;
const filePath = `chat/public/${uuidv4()}.jpg`; // uuid is a function that creates random string
this.setState({
uploadState: 'uploading',
uploadTask: this.state.storageRef.child(filePath).put(file,metadata)
},
() => {
this.state.uploadTask.on('state_changed', snap => {
const percentUploaded = Math.round((snap.bytesTransferred / snap.totalBytes) * 100)
this.setState({percentUploaded})
},
err => {
console.error(err)
this.setState({
errors: this.state.errors.concat(err),
uploadState: 'error',
uploadTask: null
})
})
},
() => {
this.state.uploadTask.snapshot.ref.getDownloadURL().then(downloadUrl => {
console.log(downloadUrl) // get error
this.sendFileMessage(downloadUrl, ref, pathToUpload)
})
.catch(err => {
console.error(err)
this.setState({
errors: this.state.errors.concat(err),
uploadState: 'error',
uploadTask: null
})
})
}
)
};
If you need more code let me know, but on this point where i log error it's where the problem is.
Simply url of posted image in the DB can't be retrieved, i tried with storage rules but there everything looks fine.
EDIT: With state_changed listener state doesn't change - whole time it stays at 'uploading' while image is being stored in storage
It looks like you're not waiting for the upload to fully complete before requesting the download URL. This is usually what a 404 means with this sort of code. You're going to have to use the promise returned by storageRef.child(filePath).put(file,metadata) in order to know when the upload is complete, and only then will you be able to call getDownloadURL() successfully on its reference.
I want to build a CRUD in React with Laravel and Firebase. Everything is perfect when I'm working with text, but I got trouble when I try to upload an image to Firebase Storage. I can save it but I can't get its URL.
I wrote 2 "console.log". In the first one the URL is there, but the second one (when I try to get the URL from the state variable) doesn't return anything.
handleSubmit = event =>{
event.preventDefault();
const {imagen} = this.state;
if(imagen!=null){
const uploadTask = storage.ref(`imagenes/${imagen.name}`).put(imagen);
uploadTask.on('state_changed',
(snapshot) => {
const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100);
this.setState({progress});
},
(error) => {
console.log(error);
},
() => {
storage.ref('imagenes').child(imagen.name).getDownloadURL().then(url => {
this.setState({url});
console.log(this.state.url); //<<<<<<<<<<<<<SHOW URL (IT'S OK!)
})
});
}
var direccion = null;
const form = event.target;
let data = new FormData(form);
data.append('url', this.state.url);
console.log(this.state.url); //<<<<<<<DOESN'T SHOW URL !! (HERE'S THE TROUBLE)
If you want to check the entire file:
https://github.com/AndresVasquezPUCE/project/blob/master/pelicula
I'm not a professional, so please don't be rude :D
this.setState is asynchronous
If you want to get the updated state value, add a callback and access the new state there like
this.setState({ url: 'some url'}, () => {
conosle.log(this.state.url);
});
Data is loaded from Firebase asynchronously. By the time your console.log(this.state.url); //<<<<<<<DOESN'T SHOW URL !! (HERE'S THE TROUBLE) the data hasn't been loaded from Firebase yet, and the then hasn't been called yet.
Any code that needs the data from Firebase needs to either be inside the then() callback (such as console.log(this.state.url); //<<<<<<<<<<<<<SHOW URL (IT'S OK!)) or be called from there (such as this.setState({url})).