Can't get data from firebase - javascript

I can't get data from firebase. Firebase.js is using for initialization of firebase and in App.js I am trying to get and work with it.
Now when I'm trying to get data and display it in browser, I see just blank page. Looks like I didn't get any data.
In some reasons I even can't console.log from stocksRef.on('value', (dataSnapshot) and I can't check what data I got and did I get it.
Please, help me to fix it.
App.js
class StocksList extends Component {
constructor(props){
super(props);
this.state = {
stocks: []
}
}
componentDidMount() {
const stocksRef = firebase.database().ref('list');
console.log('popopok', stocksRef)
stocksRef.on('value', (dataSnapshot) => {
let list = dataSnapshot.val();
this.setState({
stocks: Object.values(list)
})
})
}
render() {
return (
<div>
{this.state.stocks.map((item) => {
return (
<div>
<p>ISIN: {item.isin}</p>
<p>issuer: {item.issuer}</p>
<p>issuerCode: {item.issuerCode}</p>
<p>ISIN: {item.isin}</p>
<p>nominal: {item.nominal} {item.currency}</p>
<p>form: {item.form}</p>
<p>vyd: {item.vyd}</p>
</div>
)
})}
</div>
)
}
}
export default StocksList;
firebase.js
import firebase from 'firebase'
let config = {
apiKey: ******,
authDomain: ******,
databaseURL: ******,
projectId: ******,
storageBucket: ******,
messagingSenderId: ******,
appId: ******
};
firebase.initializeApp(config);
export default firebase;

You need to make access permission rules at firebase console.
As far as I know you need to make some rules for Access data in firebase real-time-database.
And If you want to know about firebase permission rule, just read my reference
You can check it with next code's error
try{
stocksRef.on('value', (dataSnapshot) => {
let list = dataSnapshot.val();
this.setState({
stocks: Object.values(list)
})
})
} catch(error) {
console.log(error);
}
Reference
Database rules - Firebase Documents

Try like this
async componentDidMount() {
const stocksRef = await firebase.database().ref('list');
console.log('popopok', stocksRef)
stocksRef.on('value', (dataSnapshot) => {
let list = dataSnapshot.val();
this.setState({
stocks: Object.values(list)
})
})
}

Related

How to fix error that my Vue app doesn't get data from Firebase?

I made a Firebase app with database, connected it with Vue app, which is like todo-list. I tried to get a data from database from firebase, which is used to make components for app, but something got wrong. Vue app doesn't get the data from firebase, so items aren't created
It's th error:
#firebase/firestore: Firestore (9.10.0): Uncaught Error in snapshot listener: {"code":"permission-denied","name":"FirebaseError"
Initializing firebase:
import { initializeApp } from "firebase/app";
import { getDatabase } from "firebase/database";
import { getFirestore } from "#firebase/firestore";
const firebaseConfig = {
apiKey: "AIzaSyBZlP_E74i40ZLopttFlUbg3j36wirKf9A",
authDomain: "quotes-app-8788c.firebaseapp.com",
projectId: "quotes-app-8788c",
storageBucket: "quotes-app-8788c.appspot.com",
messagingSenderId: "934346412075",
appId: "1:934346412075:web:5da2928fecb05c834f5a6e"
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
export {
db
}
Here is my code:
onSnapshot(collection(db, 'quotes'), (QuerySnapshot) => {
const fbquotes = [];
QuerySnapshot.forEach((doc) => {
const quote = {
id: doc.data().id,
quoteText: doc.data().quoteText,
quoteAuthor: doc.data().quoteAuthor,
quoteGenre: doc.data().quoteGenre,
timeCreating: doc.data().timeCreating,
timeEditing: doc.data().timeEditing
}
this.fbquotes.push(quote)
})
this.quotes = fbquotes
console.log(this.quotes);
})
console.log(this.quotes);
},
The error code "permission-denied" tells that your security rules are not allowing the user to query that whole collection. If a user can read all documents from the "quotes" collection then make sure you have the following rules:
match /quotes/{quotesId} {
allow read: if true;
}
You can change the condition for allow read if your requirements are different. Also Security Rules are not filters so if you want to allow a user to read their own documents only, then make sure you change the query in your code as well to match the security rules.

How do I get first call to Firebase to work?

Every time I reload my web app the first time I try call getDBRecords() it doesn't work (the code inside the then statement doesn't execute), but then if I try again immediately it will work, and will continue to work from then on until I reload the app.
How can I get the DB call to work first time? Is it something to do with Promises /Async await?
Any help is much appreciated!
firebase.js Installation/Configuration
import * as firebase from 'firebase'
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: "",
databaseURL: ""
};
let app
if (firebase.apps.length === 0) {
app = firebase.initializeApp(firebaseConfig)
} else {
app = firebase.app();
}
const auth = firebase.auth()
const db = firebase.firestore();
export { db, auth };
DataContext
import React, { useContext, useState, useEffect } from 'react'
import { db } from '../../firebase'
const DataContext = React.createContext()
export function useData() {
return useContext(DataContext)
}
export function DataProvider({ children }) {
const [result, setResult] = useState('')
function getDBRecords() {
setResult('')
var results = []
var promise = db.collection("COLLECTION_NAME").where("attr", ">", 10).get()
promise.then((querySnapshot) => {
querySnapshot.forEach((doc)=>{
results.push(doc.data())
})
setResult(results)
}).catch((error) => {
console.log("Error getting document:", error);
});
return result
}
const value = {
testDBRead,
testDBWrite,
getLastFew,
propSearch
}
return (
<DataContext.Provider value={value}>
{children}
</DataContext.Provider>
)
You should call your function in useEffect
useEffect(() => {
getDBRecords();
},[])
Figured it out, posting the answer for anyone else who runs into the problem.
I needed to give the then() function after the promise a function it could callback, I think, not sure how it works but by passing the useState set state function into my useContext() and calling that function inside my then function the data is updated.
In the screen.js file:
// Importing the function from a useContext
const { fetchSingleDoc } = useData()
const [doc, setDoc] = useState('')
// Here I call the fetchSingleProp and pass both the ID of the document I wish to get and the setter function.
const handleFetchDoc = (doc_id) => {
console.log("Fetching Property: ", x)
fetchSingleProp(doc_id, setDoc)
}
In the DataContext.js file:
// The solution for me was to add the setDoc function and call it inside the then call.
function fetchSingleDoc(prop_id, setDoc) {
var propRef = db.collection("PROD-JOIN").doc(props[prop_id]);
propRef.get().then((doc) => {
if (doc.exists) {
const data = doc.data()
setDoc(data)
} else {
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}
Not really sure whats happening but I think the then part of the statement hasnt returned and so needs a function it can "call back" to pass the value back to the right place.

firebase.database.ref is not a function React Native / Expo

I am pretty new to expo and firebase, and I have this error that I have no idea what the issue is. I am trying to fetch photos from firebase database. I know for sure the issue is not with firebase config because I can upload photos into firebase storage.
I suspect the issue is with exporting and importing firebase.
This is the error message I am getting :
[TypeError: _firebase.db.ref is not a function. (In
'_firebase.db.ref('users/photos')', '_firebase.db.ref' is undefined)]
Note: I am using firebase v9
App.js file:
import { db } from './firebase';
export default function App() {
async function loadPhotos() {
try {
db.ref('users/photos')
.then(url => {
console.log('URL: ', url);
})
.catch(e => console.log(e));
console.log('Got here');
} catch (error) {
console.log('error', error);
}
}
...............
}
firebase.js file:
import firebase from 'firebase/compat/app';
import { getDatabase } from 'firebase/database';
const firebaseConfig = {
apiKey: '......',
authDomain: '.....',
projectId: '....',
storageBucket: '....',
messagingSenderId: '....',
appId: '.....',
measurementId: '....',
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
export const db = getDatabase();
In v9 and later of the Firebase SDK, most functionality that was a method on the objects in the past, is now available as a top-level function.
So instead of db.ref('users/photos'), you need to do ref(db, 'users/photos').
You're also missing a get call, which is how you actually retrieve the data from the reference:
get(ref(db, 'users/photos'))
.then(url => {
console.log('URL: ', url);
})
.catch(e => console.log(e));
This is all pretty well documented in the Firebase documentation on reading data, so I recommend keeping that handy. Alternatively you can use the compat paths in v9, to make the older syntax work as shown in the upgrade guide/

Web firebase.messaging().onMessage not fired, but background notification perfectly fired

I want to reload or trigger some event in foregrounf if push message is sent with firebase.messaging().onMessage, but it not fired. I'm using firebase.mesaging.sw.js with background notification and it works correctly what is wrong with my code?
firebase.js
const config = {
apiKey: "x",
projectId: "x",
storageBucket: "x",
messagingSenderId: "x"
};
firebase.initializeApp(config);
const msg = firebase.messaging()
msg.requestPermission()
.then(() => {
return msg.getToken()
})
.then((token) => {
})
.catch((err) => {
})
msg.onMessage(function(payload) {
alert("Foreground message fired!")
console.log(payload)
});
firebase.messaging.sw.js
importScripts("https://www.gstatic.com/firebasejs/7.0.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.0.0/firebase-messaging.js");
const config = {
apiKey: "x",
projectId: "x",
storageBucket: 'x',
messagingSenderId: "x"
};
firebase.initializeApp(config);
const msg = firebase.messaging()
msg.setBackgroundMessageHandler(function(payload) {
let options = {
body: payload.data.body,
icon: payload.data.icon
}
return self.registration.showNotification(payload.data.title, options);
});
I don't know what is wrong with my code
Simple solution to this is update your Firebse to latest version.
Eg.
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
Note: Once you have updated your firebase libraries versions then messagingSenderId will not work in your firebase-messaging-sw.js file. You have to provide all other params eg. apiKey, projectId, appId along with messagingSenderId.
If still not work. Clean your browser cache and re-register service worker.
For more details you can refer to this solution
Still had the same issue in 2020. In my case it was like this:
you need to have same versions in importScripts for background messages and in your app for foreground messages
call it after obtaining token for background service
firebaseApp.messaging().getToken().then((currentToken) => {
if (currentToken) {
console.log(currentToken)
} else {
// Show permission request.
console.log(
'No Instance ID token available. Request permission to generate one.')
}
/** When app is active */
firebase.messaging().onMessage((payload) => {
console.log(payload)
}, e => {
console.log(e)
})
})
For anyone else with this problem, I finally solved it by:
Upgrading the Firebase SDK version in both header-included JS files and the SW JS file to latest (currently, that would be 7.8.1).
Adding the entire firebaseConfig array to the SW firebase.initializeApp(), as the previous answer suggests.
Cleaning the Chrome cache from the Application > Clear Storage section in the Developer Tools.
Deleting the previous registration token from my database.
Blocking and unblocking notifications from the browser to force a new token generation.
Basically, a total fresh start with updated Firebase SDK seems to fix issues like this.
You are missing lots of things and onMessage will only work if firebase is initialized before calling it. Please follow this. I have done it like this and it is working.
initialize firebase and get the token
export class BrowserFcmProvider {
export const FIREBASE_CONFIG = {
apiKey: "****",
authDomain: "****",
databaseURL: "****",
projectId: "****",
storageBucket: "****",
messagingSenderId: "****",
appId: "****"
}
firebase.initializeApp(FIREBASE_CONFIG);
async webGetToken() {
try {
const messaging = firebase.messaging();
await messaging.requestPermission();
const token = await messaging.getToken();
let uuidTemp = new DeviceUUID().get();
return this.saveTokenToFireStoreFromWeb(token, uuidTemp)
} catch (e) {
console.log(e);
}
}
saveTokenToFireStoreFromWeb(token, uuid) {
try {
const docData = {
token: token,
device_type: 'web',
uuid: uuid
}
const devicesRef = this.db.collection('devices')
return devicesRef.doc(uuid).set(docData);
} catch (e) {
console.log(e, 'saveTokenError');
}
}
showMessage() {
try {
const messaging = firebase.messaging();
messaging.onMessage((payload) => {
console.log(payload);
})
} catch (e) {
console.log(e)
}
}
}
And calling the method while app loads like this
async configureFirebaseForBrowser(res) {
await this.bfcm.webGetToken();
this.bfcm.showMessage();
}
Firebase function and payload type
const payloadWeb = {
title: title,
body: body,
data: {
title: title,
body: body
},
tokens: uniqueDevicesTokenArrayWeb,
}
const responseWeb = await admin.messaging().sendMulticast(payloadWeb);
console.log(responseWeb.successCount + ' notifications has been sent to Web successfully');
I have used async and await as we need to manage firebase/firestore operations asynchronously.
fcm does not work in Incognito mode and safari browser
Same issue i was faced. In my case firebase version in "package.json" and "firebase-messaging-sw.js" importScripts version was different. After set same version in "firebase-messaging-sw.js" importScripts which was in
"package.json", my issue is resolved.
Before change
**"package.json"**
"firebase": "^8.2.1",
**"firebase-messaging-sw.js"**
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
After change
**"package.json"**
"firebase": "^8.2.1",
**"firebase-messaging-sw.js"**
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-messaging.js');

Vue.Js with Firebase cloud firestore, adding items to database is triggered twice

I want to send an Item to my database collection in firestore, for some reason the add() function gets executed twice so the same object is sent two times with different autogenerated Id, which is obviously not the desired behavior, below is the file from which I initialize my firebase app.
import firebase from 'firebase'
// Initialize Firebase
var config = {
apiKey: "**********",
authDomain: "*******",
databaseURL: "https://*****.firebaseio.com",
projectId: "my-****",
storageBucket: "****.appspot.com",
messagingSenderId: "*******"
};
const firebaseApp = firebase.initializeApp(config);
firebaseApp.firestore().settings({ timestampsInSnapshots: true })
export default firebase.firestore()
now this code below is how i trigger the add() function to send the item to the database from my .vue file
import db from '../firebase/init.js';
export default {
...
methods: {
addNewItem(){
let item = {
row1: 'record one,
row2: 'record two,
}
db.collection('myItems').push(item)
.then(doc => console.log(doc))
.catch(err => console.log(err))
}
}
}
please let me know in a comment below if any additional information is needed for better clarifying the issue. thanks in advance.

Categories

Resources