// db.js file
import * as firebase from "firebase/app"
import "firebase/database"
const config = {
apiKey: "" ...
}
const db = firebase.initializeApp(config)
export default db
// App.vue file
import { reactive, onMounted, ref } from 'vue'
import db from "./db.js";
const SendMessage = () => {
const messagesRef = db.database().ref("messages")
if(inputMessage.value === "" || inputMessage.value === null) {
return
}
const message = {
username: state.username,
content: inputMessage.value
}
messagesRef.push(message)
inputMessage.value = ""
}
I try to make a little chat app with Vue.js and Firebase.
So i don't understand because i receive this when i try to send a message :
db_js__WEBPACK_IMPORTED_MODULE_1_.default.database is not a function
at Proxy.SendMessage (App.vue?3dfd:63:1)
I think it's about the import but i try to change for the V9 of firebase but that's didn't work.
Firebase V9 is build in functional aproach. Im working with firestore usually give me a sign if some thing not working.
db.js
import { initializeApp } from 'firebase/app';
import { getDatabase, ref, push, child, serverTimestamp } from 'firebase/database'
const config = {
apiKey: "" ...
}
const firebase = initializeApp(config)
const db = getDatabase()
function addMessage(path, message) {
message.createAt = serverTimestamp() // On database side database will assign current
// timestamp to this field so you will be able to order data
// from newest to oldest for example.
return push(child(ref(db, path)), message)
}
export { addMessage }
App.vue file
import { reactive, onMounted, ref } from 'vue'
import { addMessage } from "./db.js";
const SendMessage = async () => {
if (!inputMessage.value) return
// line above will check are value is "" or null by throwing
// false and using ! in front you changing it to true.
const message = {
username: state.username,
content: inputMessage.value
}
const result = await addMessage('path to data in tree', message)
// async/await will await until data is saved in database and then will do code bellow.
console.log(result.key) // If you await you can read result if result is not void.
inputMessage.value = ""
}
If you use ref() in .vue files make database operations outside of vue files database have same ref() function but they work different. You can allso change name of one function in import line import { ref as dbRef } from 'firebase/database'
Related
as I continue to work on my issues I've got one that's kind of perplexing. my app has two JS files that interact with each other, but what's odd is it seems that then I call the function to get the data from firestore it seems that it wants to run it twice.
Here is the HomeScreen.js file that is suppoed to call UserInformation
import { Pressable, Text } from 'react-native';
import { useEffect, useId, useState } from 'react';
import { async } from '#firebase/util';
import { FlatList } from 'react-native-gesture-handler';
import {getStorage, ref, getDownloadURL} from 'firebase/storage';
//import the user infomration component
import UserInformation from '../components/UserInformation';
import ClubInformation from '../components/ClubInformation';
import AircraftInformation from '../components/AircraftInformation';
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
if (userDetails !== null) {
//console.log(userDetails)
//console.log(clubDetails)
//console.log(aircraftDetails)
}
if(!userDetails) {
return <Text>Loading...</Text>
}
if(!clubDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>
}
export default HomeScreen
the userDetails calls is below:
userInformation.js
import { useState, useEffect } from "react";
import { getAuth } from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import { db } from '../components/FirebaseConfig';
export default function UserInformation() {
const [userDetails, setUserDetails] = useState(null);
useEffect(() => {
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
setUserDetails(data);
} else {
console.log("No such User!");
}
}
getUserDetails();
}, []);
return userDetails;
}
Whenever I do a console log from the HomeScreen it seems to first return null, then it returns the data. Is there something I'm doing wrong here (I'm sure it is) or is it standard behavior? Thank you in advance
I tried to run this multiple ways but those other functions that i have that also query the db seem to do the same thing. I don't know if it's something up with my async
This is expected behavior when UserInformation function is working as a custom hook.
The first time when HomeScreen component was initialized/mounted, the default value userDetails is null.
After a few seconds, the app fetches data from Firestore and updates userDetails state value which trigger a second rerender.
Note: Recommended best practice is always prefixed custom hooks function name use[FUNCTION_NAME] like useUserInformation.
Your logic is completely wrong. You couldn't wait on referencing hook function.
Even you can use useEffect hook if you want to get valid response.
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
useEffect(()=>{
if (userDetails) {
console.log(userDetails)
}
}, [userDetails])
if(!userDetails) {
return <Text>Loading...</Text>
}
if(!clubDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>
}
As I said in my comment you don't need to create your custom hook functions. It's enough with normal functions it will work like this.
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
return data;
} else {
console.log("No such User!");
return null
}
}
function HomeScreen() {
const [userDetails, setUserDetails] = useState(null)
useEffect(()=>{
getUserDetails().then(data=>{
if (data != null) {
setUserDetails(data)
}
})
}, [])
if (!userDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last}</Text>
}
So this is my problem:
import sanityClient from '#sanity/client';
export const client = sanityClient({
projectId: import.meta.env.VITE_APP_SANITY_PROJECT_ID ,
dataset: 'production',
apiVersion: '2022-09-08',
useCdn: true,
token: import.meta.env.VITE_APP_SANITY_TOKEN,
ignoreBrowserTokenWarning: true
});
for this project i use sanity client
import { useState,useEffect } from 'react'
import {client} from './client'
function App() {
const [User, setUser] = useState()
useEffect(()=>{
const getUserData=()=>{
const query = `*[_type == "user" && _id == 'John']`;
client.fetch(query).then((data)=>{
console.log(data[0]) //return data as expected
setUser(data[0])
console.log(User) //return undefined
})
}
getUserData()
},[])
Why when i reload the page setUser don't work inside useEffect and return undefined?
You will. not get data instantly
use new useEffect like this
import { useState,useEffect } from 'react'
import {client} from './client'
function App() {
const [User, setUser] = useState()
useEffect(()=>{
const getUserData=()=>{
const query = `*[_type == "user" && _id == 'John']`;
client.fetch(query).then((data)=>{
setUser(data[0])
})
}
getUserData()
},[])
useEffect(()=>{
if (User) {
console.log(User)
}
},[User])
You wont get any log, but your code is correct. It's because
setState(updater[, callback])
setState tells its children and the component needs to be rerendered.
So you wont get immeditately the changed state value. If you console log before the useState, you'll see
at first its showing undefined but after rerendering you'll get the updated state value.
I'm trying to set data to my realtime database on firebase. I have used the following code.
I am passing my database name as well as the region in my url still getting this error. Is there anyone who know's what is wrong with the code.
Error "firebase.database(app) arg expects a FirebaseApp instance or undefined.Ensure the arg provided is a Firebase app instance; or no args to use the default Firebase app." I have also initialised the firebase config.
Also I am getting the same problem while fetching data.
import {EMPLOYEE_UPDATE,EMPLOYEE_CREATE,} from './types';
import database from '#react-native-firebase/database';
import auth from '#react-native-firebase/auth';
import { firebase } from '#react-native-firebase/app';
import { Actions } from 'react-native-router-flux';
export const employeeUpdate = ({prop,value}) => {
return {
type: EMPLOYEE_UPDATE,
payload: {prop,value},
};
};
export const employeeCreate = ({name,phone,shift}) => {
const {currentUser} = auth();
return (dispatch) =>{
*const ref = database(
'https://managerproject-8924c-default-rtdb.asia-southeast1.firebasedatabase.app/')
.ref(`/users/${currentUser.uid}/employees`);
console.log(ref);
ref.set({name,phone,shift})
.then(()=> {*
console.log('Data set.');
dispatch({type: EMPLOYEE_CREATE });
Actions.employeeList({type: 'reset'});
});
};
};
As Firebase realtime database documentation,
So, the code will be:
import { firebase } from '#react-native-firebase/database';
firebase
.app()
.database('https://managerproject-8924c-default-rtdb.asia-southeast1.firebasedatabase.app/'))
.ref(`/users/${currentUser.uid}/employees`)
.set({name,phone,shift})
.then(() => console.log('Data set.'))
.catch((error) => console.log(error));
Inside my index.js file:
export function postArticleAPI(payload) {
return(dispatch) => {
const upload = storage
.ref(`images/${payload.image.name}`)
.put(payload.image);
upload.on("state_changed", (snapshot) => {
const progress = (
(snapshot.BytesTransferred / snapshot.totalBytes) * 100);
console.log(`Progress: ${progress}%`);
if(snapshot.state === "RUNNING") {
console.log(`Progress: ${progress}%`);
}
},
(error) => console.log(error.code),
async() => {
const downloadURL = await upload.snapshot.ref.getDownloadURL();
db.collection("articles").add({
...
});
});
}
};
}
I look in the docs provided by firebase but I am unsure how to implement that. When I run the code above, I get "TypeError: firebase__WEBPACK_IMPORTED_MODULE_0_.storage.ref is not a function" error.
I messed around with the code and I've also gotten other errors such as: "...storage.put is not a function," I've gotten errors with upload, as well as db.collection error.
Here's my firebase.js:
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider } from 'firebase/auth';
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
...
}
const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore(firebaseApp);
const auth = getAuth();
const provider = new GoogleAuthProvider();
const storage = getStorage(firebaseApp);
export { auth, provider, storage };
export default db;
Any help would be appreciated (and this is my first post, so please let me know if I need to add anything else). Thanks!
Since you're using the v9 syntax for importing top-level functions, there is no longer a storage.ref() method. Instead, as shown in the documentation on getting a reference and uploading files, you can do:
const ref = ref(storage, `images/${payload.image.name}`)
const upload = uploadBytes(ref, payload.image);
I'm new to react, and I am trying to push to a new page through a function. The function is createCheckoutSession... here's what I have.
export async function createCheckoutSession(activtyStatus){
let user = firebase.auth().currentUser;
if (user == null) {
this.props.history.push(routes.CLIENTS)
}
how to I declare this.props, or how do I actually push the new page? It is logging error:
'props' is not defined no-undef
here is my entire page.
import { loadStripe } from '#stripe/stripe-js';
import firebase from 'firebase';
import "firebase/auth";
import * as routes from '../routes';
import './checkout.css';
import React, { useState, useEffect } from "react";
import MyGifSpinner from './manageSubSpinner';
import './manageSubSpinner.css';
import ReactDOM from 'react-dom';
import myGif from '../pages/spinner';
import myGifSpinner from './manageSubSpinner';
import { doSignOut } from '../models/AuthorizationHome';
const firestore = firebase.firestore();
const app = firebase.app();
export async function createCheckoutSession(activtyStatus){
let user = firebase.auth().currentUser;
if (user == null) {
this.props.history.push(routes.CLIENTS)
}
console.log(user)
//price ID with trial LIVE ID
var price = 'price_1IGW85KDPaWWeL1yjWsi9oRa'
// var price = 'price_1Iav0JKDPaWWeL1yBa9F7Aht'
firestore.collection('customers').doc(user.uid).collection('subscriptions').get().
if (activtyStatus == "canceled") {
console.log("sub is cancelled")
//live price
price = 'price_1IfmDsKDPaWWeL1ywjMTGarh'
}
console.log("activity status is: " + activtyStatus)
const checkoutSessionRef = await firestore
.collection('customers')
.doc(user.uid)
.collection('checkout_sessions')
.add({
price: price,
success_url: "http://localhost:3000/clients",
cancel_url: "http://localhost:3000/signin",
});
// Wait for the CheckoutSession to get attached by the extension
checkoutSessionRef.onSnapshot(function (snap) {
const { error, sessionId } = snap.data();
if (error) {
console.log(`An error occured: ${error.message}`);
return;
}
if (sessionId) {
const stripe = window.Stripe('pk');
console.log("going to stripe: ")
// this.setState({ isRegistering: true });
console.log("line 116 checkout.js")
stripe.redirectToCheckout({sessionId: sessionId})
console.log("logged stripe")
}
});
}
it is basically a function to call stripe, and open the stripe checkout page in the new window. So I am trying to catch if the user == null, and if true, the push them to sign in page
As I have already said, you cant use this in a React function since it is stateless, so you need to useHistory. So you need to this to your code
import { useHistory } from "react-router-dom";
export async function createCheckoutSession(activtyStatus){
let history = useHistory();
let user = firebase.auth().currentUser;
if (user == null) {
history.push(routes.CLIENTS)
}
...