I am new in react. Last day i tried to do work with Firebase in a react JS project. But i stuck on that. I set up sign in method according to the Firebase and i wanted to display all display name,email,photoUrl from the user who are sign in through sign in button.But i faced a problem i couldn't show these data but my console said i passed data successfully. I saw all data by console but why i don't show on the page. I try to fix all error but it's not change anything.My code is below:
import './App.css';
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import firebaseConfig from './firebase.confige';
import React,{useState} from 'react';
// firebase.initializeApp(firebaseConfig)
if(!firebase.apps.length){
firebase.initializeApp(firebaseConfig);
}
function App() {
const [user,setUser] = useState(
{
isSignIn: false,
name: '',
email: '',
photo: ''
})
console.log(user)
const provider = new firebase.auth.GoogleAuthProvider();
const handleSignIn = ()=>{
firebase.auth().signInWithPopup(provider)
.then(res => {
const {displayName, photoURL, email} = res.user;
const signedInUser = {
isSignIn:true,
name: displayName,
email: email,
photo:photoURL
}
setUser(signedInUser);
// console.log(displayName,email,photoURL);
})
.catch(err => {
console.log(err);
console.log(err.message);
})
}
return (
<div className="App">
<button onClick={handleSignIn}>Sign In</button>
{
user.isSignedIn &&
<div>
<p> Welcome, {user.name}</p>
<p>Your email: {user.email}</p>
<img src={user.photo} alt=""/>
</div>
}
</div>
);
}
export default App;
firebase.Confige.js file is here:
const firebaseConfig = {
apiKey: "AIzaSyBPt45m9rGYcMJy5Ynq4PtEroNsSDYUcUM",
authDomain: "ema-john-simple-61839.firebaseapp.com",
projectId: "ema-john-simple-61839",
storageBucket: "ema-john-simple-61839.appspot.com",
messagingSenderId: "813068797804",
appId: "1:813068797804:web:297c9d66d20a005cd15549",
measurementId: "G-8DGK2DEVBS"
};
export default firebaseConfig;
first starting with sign in
console show user name email and photo
display show nothing
I didn't find out any solution please help me why this is happening i have to find out
You're checking for value user.isSignedIn in your JSX and, if truthy, are displaying your values.
However, earlier in your handleSignIn method, you adjust the property isSignIn value to true if the sign-in is successful.
You should be checking for isSignIn in your JSX instead of isSignedIn.
Related
I don't understand why I can't get data from firebase firestore database.
my error :
[FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore]
My config file with firebase config is correctly set, I can add Data with this model :
{ item: { ...event, date } }
My files structures : picture of my structure
I have correctly declared my state, I have async await with try catch.
I have used this from firebase documentation
EventList.js
import { FlatList, View, Text, StyleSheet } from "react-native";
import React, { useState, useEffect } from "react";
import { EVENTS_COLLECTION } from "../commons/constants";
import db from "../commons/services/firebase";
const EventList = () => {
const [events, setEvents] = useState([]);
return (
<View>
<FlatList
data={events}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.eventContainer}>
<Text style={styles.eventName}>{item.name}</Text>
<Text style={styles.eventDate}>{item.date.toString()}</Text>
</View>
)}
/>
</View>
);
};
firebase.Js
const firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL:
"",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: "",
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
I try to get all documents from my events collection.
My goal is to make an Calendar with event manager with firebase firestore database
In firebase.js you export db like this:
export const db = getFirestore(app);
This is a named export, therefore you will need a named import:
import { db } from '../commons/services/firebase'
// or
// import * as config from '../commons/services/firebase'
// const db = config.db
The way you import is for default exports and results in your case with undefined. Therefore firebase complains that the first argument to collection is not correct (it's undefined).
You can read more about imports here.
Try this one if EVENTS_COLLECTION returns the name of the collection correctly then you will get all documents otherwise use "Collection Name" where you write EVENTS_COLLECTION.
const fetchEvents= async () => {
await db.collection(EVENTS_COLLECTION).onSnapshot({
error: e => console.error(e),
next: (querySnapshot) => {
var data = [];
var i = 0;
querySnapshot.forEach(doc => {
data.push(doc.data());
console.log(doc.id, " => ", doc.data());
});
setEvents(data)
},
})
};
I'm working on connecting a Firestore database collection to a Next.js app. The app is very simple, as I am just fetching data and displaying it on the screen. I have a collection with two items in Firestore right now, and I'm trying to get it to console.log() to verify that it is connecting. However, when I do, the console shows me two Arrays, but they don't seem to hold any of the data from my database.
I am currently using this code to log the data to the console:
import React, { useEffect, useState } from 'react'
import {collection, getDocs} from 'firebase/firestore';
import db from '../firebase/config'
import { Box } from '#chakra-ui/react'
import ProductCard from './ProductCard'
const Products = () => {
const [products, setProducts] = useState([])
useEffect(() => {
;(async () => {
const colRef = collection(db, 'products')
const snapshots = await getDocs(colRef)
const docs = snapshots.docs.map((doc) => {
const data = doc.data()
data.id = doc.id
return data
})
setProducts(docs)
console.log(docs)
})()
}, [])
I can provide the rest of the code, if necessary.
My firebase config file looks like this:
import { initializeApp } from "firebase/app";
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: "---",
authDomain: "---",
projectId: "---",
storageBucket: "---",
messagingSenderId: "---",
appId: "---",
measurementId: "---",
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app)
export default db
The Arrays I get look like this:
The database currently looks like this:
Does anybody have an idea, or can point me in the right direction?
Thanks in advance!
From your database screenshot we can deduce that products is not a root collection but a subcollection of a document (which actually does not exist). (See last note at the bottom)
So you need to declare the CollectionReference with the entire path of the (sub)collection. We don't know the name of the root collection and we just see a part of the ID of the parent document (cocoworksco...) but you should declare the subcollection CollectionReference as follows:
let colRef = collection(db, 'rootCollection/cocoworksco.../products');
let querySnapshot = await getDocs(colRef);
// ...
Note that they are many different possibilities to declare the subcollection: For example, collection(db, 'rootCollection', 'cocoworksco...', 'products') or collection(db, 'rootCollection', 'cocoworksco.../products'); are also valid.
Note also that we are actually not sure that the path of the subcollection is composed of three parts since we don't see the full path on the screenshot. It is possible that it is deeper, e.g. rootCollection/doc1/subCol1/cocoworksco.../products.
I am trying to set up Firebase with next.js. I am getting this error in the console.
FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore
This is one of my custom hook
import { onAuthStateChanged, User } from '#firebase/auth'
import { doc, onSnapshot, Unsubscribe } from 'firebase/firestore'
import { useEffect, useState } from 'react'
import { auth, fireStore } from './firebase'
export const useUserData = () => {
const [username, setUsername] = useState<string | null>(null)
const [currentUser, setCurrentUser] = useState<User | null>(null)
useEffect(() => {
let unsubscribe: void | Unsubscribe
onAuthStateChanged(auth, (user) => {
if (user) {
setCurrentUser(user)
// The Problem is inside this try blog
try {
// the onsnapshot function is causing the problem
console.log('firestore: ', fireStore)
unsubscribe = onSnapshot(doc(fireStore, 'users', user.uid), (doc) => {
setUsername(doc.data()?.username)
})
} catch (e) {
console.log(e.message)
}
} else {
setCurrentUser(null)
setUsername(null)
}
})
return unsubscribe
}, [currentUser])
return { currentUser, username }
}
I also have this firebase.ts file where I initialized my firebase app
import { FirebaseApp, getApps, initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore/lite'
import { getStorage } from 'firebase/storage'
const firebaseConfig = {
apiKey: 'some-api',
authDomain: 'some-auth-domain',
projectId: 'some-project-id',
storageBucket: 'some-storage-bucket',
messagingSenderId: 'some-id',
appId: 'some-app-id',
measurementId: 'some-measurement-id',
}
let firebaseApp: FirebaseApp
if (!getApps.length) {
firebaseApp = initializeApp(firebaseConfig)
}
const fireStore = getFirestore(firebaseApp)
const auth = getAuth(firebaseApp)
const storage = getStorage(firebaseApp)
export { fireStore, auth, storage }
I don't know whether the problem is in the project initialization. I am pretty sure the error is generated from my custom hook file. I also found out that there must be something wrong with onSnapshot function. Am I passing the docRef wrong or something? What am I doing wrong here?
The console.log(firestore) log:
type: "firestore-lite"
_app: FirebaseAppImpl
_automaticDataCollectionEnabled: false
_config: {name: "[DEFAULT]", automaticDataCollectionEnabled: false}
_container: ComponentContainer {name: "[DEFAULT]", providers: Map(15)}
_isDeleted: false
_name: "[DEFAULT]"
_options:
apiKey: 'some-api'
authDomain: 'some-auth-domain'
projectId: 'some-project-id'
storageBucket: 'some-storage-bucket'
messagingSenderId: 'some-id'
appId: 'some-app-id'
measurementId: 'some-measurement-id'
[[Prototype]]: Object
automaticDataCollectionEnabled: (...)
config: (...)
container: (...)
isDeleted: (...)
name: (...)
options: (...)
[[Prototype]]: Object
_credentials: Q {auth: AuthInterop}
_databaseId: H {projectId: "next-firebase-fireship", database: "(default)"}
_persistenceKey: "(lite)"
_settings: ee {host: "firestore.googleapis.com", ssl: true, credentials: undefined, ignoreUndefinedProperties: false, cacheSizeBytes: 41943040, …}
_settingsFrozen: false
app: (...)
_initialized: (...)
_terminated: (...)
Using getFirestore from lite library will not work with onSnapshot. You are importing getFirestore from lite version:
import { getFirestore } from 'firebase/firestore/lite'
Change the import to:
import { getFirestore } from 'firebase/firestore'
From the documentation,
The onSnapshot method and DocumentChange, SnapshotListenerOptions, SnapshotMetadata, SnapshotOptions and Unsubscribe objects are not included in lite version.
Another reason for this error to show up could be passing invalid first argument to collection() or doc() functions. They both take a Firestore instance as first argument.
// Ensure that "db" is defined and initialized
const db = getFirestore();
// console.log(db);
const colRef = collection(db, "collection_name");
Don't mix usage of firestore/lite with firestore
You need to use in your imports either:
'firebase/firestore'
OR
'firebase/firestore/lite'
Not both in the same project.
In your case, the firebase.ts file is using:
import { getFirestore } from 'firebase/firestore/lite'
And in your hook:
import { doc, onSnapshot, Unsubscribe } from 'firebase/firestore'
So you're initialising the lite but using the full version afterwards.
Keep in mind that both has it's benefits, but I would suggest in your case to pick one and just use it. Then the error will be gone.
Adding to #Dharmaraj, if you are using firebase react hooks, use the reverse.
Instead of
import { getFirestore } from 'firebase/firestore'
Use
import { getFirestore } from 'firebase/firestore/lite'
If you are using firebase lite then collection is not used.
Firebase lite example:
import {
getFirestore,
getDoc,
updateDoc,
doc
} from '#firebase/firestore/lite';
const firestore = getFirestore(app);
const docRef = doc(firestore, 'collection/doc');
const docSnap = await getDoc(docRef);
await updateDoc(docRef, "field", 'value');
When to use Firestore Lite
It can be tricky to decide when to let go of the standard Firestore SDK's offline persistence and caching features. You should understand these features before deciding to trade them away for the lower overhead of Firestore Lite. In general, weigh these factors when deciding whether to use Firestore Lite:
Online status - Firestore Lite is good for apps that do not need live updates and have connectivity.
Size constraints - Firestore Lite is great if you want to reduce your overall JavaScript bundle size.
Read more here
This can happen if you have both #firebase/firestore and firebase installed and there is a version mismatch.
firebase comes with #firebase/firestore. Remove any #firebase/... dependencies so that you're using the same version that firebase uses.
This is my first time using a useEffect hook. what its doing is reading the database to see if a value returns and if a value returns thats the userToken which is sign of an account so it signs you in. However, I have 2 problems. The Link name button doesnt automatically sign you in, instead you have to type another letter in the input box after to sign in. I tried fixing this by adding connectUser under writeUserData on line 49 but that just makes the site crash. My second problem is I cant display {userToken} on the page after bewing signed in. I recieve Error: Objects are not valid as a React child (found: object with keys {username}). If you meant to render a collection of children, use an array instead.
import React, { useState, useEffect } from "react";
import {initializeApp} from 'firebase/app';
import { getDatabase, ref, set, child, get} from 'firebase/database';
export default function Username(props) {
const [userName, setUsername] = useState('');
const [userToken, setuserToken] = useState('')
const clientCredentials = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
}
const app = initializeApp(clientCredentials);
const db = getDatabase();
const address = props.address;
function writeUserData(userId, userN, ) {
const reference = ref(db, 'users/' + userId);
set(reference, {
username: userN,
});
}
const dbRef = ref(getDatabase());
function connectUser() {
get(child(dbRef, `users/${address}`)).then((snapshot) => {
if (snapshot.exists()) {
setuserToken(snapshot.val());
} else {
console.log("No data available");
}
}).catch((error) => {
console.error(error);
});
}
const handleChange = (event) => setUsername(event.target.value);
function handleClick(e) {
writeUserData( address, userName);
}
useEffect(() => {
connectUser()
});
while (userToken == '')
return (
<>
<div>
<p className = "account-Info" >address: {address}</p>
</div>
<div id="form">
<h2 className='user-Create' > Username </h2>
<form id='set-User'>
<input id='username' className="user-Create" type='text' value={userName} onChange={handleChange}
required minLength='3' maxLength='30' pattern="[a-zA-Z0-9_]+" title='only letters, numbers, and underscores.'/>
<button className='user-Create' type="button" onClick={handleClick}>Link Name</button>
</form>
</div>
</>
);
while (userToken)
return (
<p className = "account-Info" >hi user</p>
);
}
First, please do not use while. Instead, use if.
if (!Boolean(userToken)) return <something />;
// No need to give condition here
// If userToken is not false, this will return
return <main />;
Second, useEffect's dependency, according to what you wrote, which is
useEffect(() => {
connectUser();
});
It means you execute connectUser() everytime any component update. Pass a dependency. If want no dependency, use [], which means execute connectUser() only once when component mounts.
useEffect(() => {
connectUser();
},[]);
Third, for Error: Objects are not valid as a React child (found: object with keys {username}), if you get similar error in future, use console.log() to debug. In your case, console.log(userToken) and go see in console of your browser.
Fourth, if you are handling about authentication, did you consider using firebase/auth?
For useEffect running multiple times, please pass in a dependency array. Check the react documentation on useEffect. You can start by giving an empty array as the second parameter to useEffect
Self taught coder here. Hopefully I'm explaining the issue adequately.
I'm trying to create some user authentication using firebase. I keep getting an error saying "Line 18:16: 'getAuth' is not defined". I'm confused because I was following a tutorial. I have tried reordering my imports as I read online that might be the reason for the error. For some reason I think my problem is in the config file and how I've initialized everything. I'm new to firebase. Any potential solves would be appreciated.
Here is my firebase.js config
import { initializeApp } from "firebase/app";
import { getFirestore } from 'firebase/firestore'
import { getAuth } from "firebase/auth";
import "firebase/storage"
const firebaseConfig = {
apiKey: "process.env.REACT_APP_FIREBASE_KEY",
authDomain: "uploadimg.firebaseapp.com",
projectId: "uploadimgofficial",
storageBucket: "uploadimg.appspot.com",
messagingSenderId: "MESSENGER_ID",
appId: "APP_ID",
measurementId: "MESAUREMENT_ID"
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth()
// Init firestore
const db = getFirestore()
export { db }
And this is where I'm trying to set up the login page
import React from "react";
import "./Login.scss";
import { useState } from "react";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../../firebase";
const Login = () => {
const [error, setError] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleLogin = (e) => {
e.preventDefault();
};
const auth = getAuth(); // <------ THIS IS ERROR LINE
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user)
})
.catch((error) => {
setError(true)
});
return (
<div className="login">
<form onSubmit={handleLogin} className="login__form">
<input
className="login__email"
onChange={e => setNewEmail(e.target.value)}
type="email"
placeholder="email" />
<input
The issue with your code is that you have imported the getAuth function incorrectly.
To fix this, you need to correct the name usage when calling the function.
As you have imported getAuth as auth in the import statement at the top of your file, you need to use it as so.
import { auth } from "../../firebase.js";
Right now, you are importing the auth variable, which is set to the return value of getAuth, as defined below in the firebase.js file.
// As you are calling the function with '()', you are getting the return value.
export const auth = getAuth();
To fix this, simply change your function call to auth. Also, rename the variable to something other than auth to avoid name collisions, and/or confusing naming patterns.
Also, as you are getting and setting the return value of getAuth to auth, the return value may not be a function1. In that case, you can't call auth with brackets (()), as, for instance, it may return an object.
// Change the variable name to what you want.
const userAuth = auth;
To check if it is a string/object/function/etc, you can use typeof (for checking/debugging; remove this line once done).
console.log(typeof auth); // Should return: 'string' | 'function' | 'object' | ...
Depending on the return type, you can change your usage to match it.
In conclusion, to fix your issue, you need to correctly use the name (auth instead of getAuth). Also, make sure to check the return value of getAuth, and use it appropriately!
1 Please correct me in the comments if I am incorrect; the return value is a function. In that case, I can remove that part. Thank you for the clarification!