I am trying to follow this tutorial.
I'm currently stuck at the step which introduces react context to firebase.
This code block is the source of the current problem:
import Firebase, { FirebaseContext } from './components/firebase';
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
<App />
</FirebaseContext.Provider>,
document.getElementById('root'),
);
serviceWorker.unregister();
When I try this, I get an error that says:
TypeError:_components_firebase__WEBPACK_IMPORTED_MODULE_5__.default is not a constructor
I have seen this post, which relates to Vue but says that the cause of an error with .default is not a constructor (not the rest of it), is because Firebase object should not be called with new keyword.
I tried removing new, but that generates an error message that says:
TypeError: Object(...) is not a function
I'm wondering if this has anything to do with the unusual way that the tutorial configures the app for firebase - which is with a class that uses a constructor (still don't understand why this is done this way):
class Firebase {
constructor() {
app.initializeApp(config);
this.auth = app.auth();
this.db = app.database();
}
export default Firebase;
Does anyone using Firebase with React know how to use the context API and if you do, have you found a way around this problem?
The firebase config setup files are:
index:
import FirebaseContext, { withFirebase } from './Context';
import Firebase from '../../firebase.1';
export default Firebase;
export { FirebaseContext, withFirebase };
context:
import React from 'react';
const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default FirebaseContext;
NEXT ATTEMPT
I found this post, which looks like it might have been trying to follow the same tutorial.
That approach requires that I add back the auth method in the firebase.1.js config file so that it now looks like this:
class Firebase {
constructor() {
app.initializeApp(config).firestore();
this.auth = app.auth();
// this.db = app.database();
// this.db = app.firebase.database()
this.db = app.firestore();
}
doCreateUserWithEmailAndPassword = (email, password) =>
this.auth.createUserWithEmailAndPassword(email, password);
}
Then, the submit handler in the form is like this:
handleCreate = values => {
values.preventDefault();
const { name, email, password } = this.state;
Firebase
.doCreateUserWithEmailAndPassword = (email, password) => {
return this.auth
.createUserWithEmailAndPassword(email, password)
.then((res) => {
Firebase.firestore().collection("users").doc(res.user.uid).set({
email: values.email,
name: values.name,
role: values.role,
createdAt: Firebase.FieldValue.serverTimestamp()
}).then(() => this.history.push(ROUTES.DASHBOARD));
})
.catch(err => {
console.log(err.message);
});
};
};
When I try this, I don't get any errors, but the form does not submit - it just hangs.
NEXT ATTEMPT
Since the FirebaseContext.Consumer includes a line with firebase in lowercase, I tried all of the same steps above, but replacing title case Firebase with lower case firebase. I also tried this.firebase (I don't know why) and this.props.firebase (I have seen other posts try that but still don't know why).
None of these approaches work either.
When I try to console.log(Firebase) above the FirebaseContext.Provider, I get this a big log with lots of drop down menus that starts with this:
FirebaseAppImpl {firebase_: {…}, isDeleted_: false, services_: {…},
tokenListeners_: Array(0), analyticsEventRequests_: Array(0), …}
INTERNAL: {analytics: {…}, getUid: ƒ, getToken: ƒ,
addAuthTokenListener: ƒ, removeAuthTokenListener: ƒ}
One of the drop down menus inside this log is labelled "options_" and includes my firebase app credentials.
I think this could be related to the problem in my recent other answer.
I managed to get new Firebase working by simplifying the import/export setup.
In the react app the imports are now:
import { FirebaseContext } from './components/context';
import Firebase from './components/firebase';
Those imports and the new work after I replaced the complicated "import and re-export" code in the components/firebase.js with simply the definition for the class Firebase from the tutorial.
After this another error Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app). pops up, but that could be because I didn't follow the whole tutorial and some configuration is missing.
Replicating everything you are dealing with is quite difficult without having the full source of your project.
Here is the test App.js I used after the npx create-react-app react-firebase-authentication and after installing firebase.
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { FirebaseContext } from './components/context';
import Firebase from './components/firebase';
function App() {
const foo = new Firebase()
return (
<div className="App">
... omitted ...
</div>
);
}
export default App;
Related
So basically the console is showing me that I have an unexpected token but I don't think there is any unexpected token. Please help me. I have taken way too much time trying to fix this problem. Here is the code -
import React from 'react';
import firebase from 'firebase';
export default function App() {
// I have deleted this information because I don't want anyone to access my data
const firebaseConfig = {};
firebase.initializeApp(firebaseConfig);
function signInWithGoogle() {
var google_provider = new firebase.auth.GoogleAuthProvider();
firebase
.auth()
.signInWithPopup(google_provider)
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
}
return (
<div>
<h1>Google Sign In Authentication</h1>
<button onClick={signInWithGoogle}>Sign In</button>
</div>
);
}
The only issue I see in the provided code is you have not imported the Firebase Auth SDK. You can import that as shown below:
import firebase from 'firebase';
import "firebase/auth"
Also make sure you are using V8.X.X or lower with above code. If you have new Modular SDK V9.0.0+ then change your imports to compat version to keep using existing code:
import firebase from 'firebase/compat/app';
import "firebase/compat/auth"
I made one react app. My app works as expected. This app's target is practice AWS-COGNITO. For Cognito validation I am using amazon-cognito-identity-js package. I made one helper function where I validate the Congnito. and reuse it in different component. I split my Nav bar into two components. From Congnito current user I made one callback function and use it in useEffect, and dependencies put the callback function, by default getAuthenticatedUser is null. I add condition where it fetch the data, if getAuthenticatedUser then redirect to signin and signup page. I deployed my app to s3 bucket and this the link. This app runs first time, When I refresh it then got error: 404 Not Found. I really don't know what is the issue and somehow the path react path get disappear. I share my code in code-sandbox.
This is my conditional path
import React from "react";
import SigninLinks from './SigninLinks';
import SignoutLinks from './SignoutLinks';
import useHandlder from '../configHandler/useHandler';
const Nav = () => {
const { getAuthenticatedUser } = useHandlder();
const Links = getAuthenticatedUser() === null ? <SignoutLinks /> : <SigninLinks />
return (
<nav className="nav-wrapper grey darken-3">
<div className="container">
<h2 className="brand-logo">Logo</h2>
{
Links
}
</div>
</nav>
);
};
export default Nav;
This is my handler functions
import React, { useCallback, useEffect } from 'react';
import { CognitoUserPool } from 'amazon-cognito-identity-js';
const Pool_Data = {
UserPoolId: "us-east-1_9gLKIVCjP",
ClientId: "629n5o7ahjrpv6oau9reo669gv"
};
export default function useHandler() {
const userPool = new CognitoUserPool(Pool_Data)
const getAuthenticatedUser = useCallback(() => {
return userPool.getCurrentUser();
},
[],
);
useEffect(() => {
getAuthenticatedUser()
}, [getAuthenticatedUser])
const signOut = () => {
return userPool.getCurrentUser()?.signOut()
}
return {
userPool,
getAuthenticatedUser,
signOut
}
};
It's paths issue. You get 404 on /path not in root /. Check S3 settings for hosting static sites. On S3 make sure static website hosting is enabled:
You react app loads on /index.html JavaScript then redirects and takes over the path. You need S3 to resolve path to index.html, then it will work.
My Problem :
I expect my FirebaseProvider function to provide an object containing all functions, through the app. The problem is that all functions are well provided through my files, except my last new function : fetchTest.
Explainations :
If I click the TestPage.js button I get Uncaught TypeError: fetchTest is not a function.
I saw many posts on stackoverflow about this type of error, but none did help me. -> I think the original problem is the index.js is not called. The console.log("firebaseprovider") (in index.js) does not appear in console, yet the other files of the project in web-app/src/views/ have the same imports and exports than TestPage.
Since App.js code worked fine on all the other files, I don't know how console.log("firebaseprovider") is never displayed in the navigator console. (edit: no matter which page I go, this console.log never appears)
<FirebaseProvider> seems to not provide TestPage.js.
Do you have an idea ?
What I've tried :
placing a console.log in TestPage.js : it shows every function written in index.js but not fetchTest. It seems to not be properly exported through api object.
in TestPage.js trying console.log("api.fetchTest") : console displays undefined.
add a second testing function in index.js, whithout parameters, which just does console.log("test")
compare imports/exports and api declarations with other files in web-app/src/views/
create a handleSubmit() function in TestPage.js to not put the functions directly in return
delete node_modules and then yarn install
yarn workspace web-app build and then relaunch yarn workspace web-app start
(This is a Yarn Workspaces project containing a common/ and a web-app/ folders)
common/src/index.js:
import React, { createContext } from 'react';
import {FirebaseConfig} from 'config';
const FirebaseContext = createContext(null);
const FirebaseProvider = ({ children }) => {
console.log("firebaseprovider"); // is not displayed in the console
let firebase = { app: null, database: null, auth: null, storage:null }
if (!app.apps.length) { // I tried to comment out this line (and the '}') -> no difference
app.initializeApp(FirebaseConfig); // no difference when commented out
firebase = {
app: app,
database: app.database(),
auth: app.auth(),
storage: app.storage(),
// [ ... ] other lines of similar code
api : { // here are functions to import
fetchUser: () => (dispatch) => fetchUser()(dispatch)(firebase),
addProfile: (details) => (dispatch) => addProfile(userDetails)(dispatch)(firebase),
// [ ... ] other functions, properly exported and working in other files
// My function :
fetchTest: (testData) => (dispatch) => fetchTest(testData)(dispatch)(firebase),
}
}
}
return (
<FirebaseContext.Provider value={firebase}>
{children}
</FirebaseContext.Provider>
)
}
export { FirebaseContext, FirebaseProvider, store }
web-app/src/views/TestPage.js:
import React, { useContext } from "react";
import { useDispatch } from "react-redux";
import { FirebaseContext } from "common";
const TestPage.js = () => {
const { api } = useContext(FirebaseContext);
console.log(api); // Displays all functions in api object, but not fetchTest
const { fetchTest } = api;
const dispatch = useDispatch();
const testData = { validation: "pending" };
return <button onClick={ () => {
dispatch(fetchTest(testData)); // Tried with/without dispatch
alert("done");
}}>Test button</button>
}
export default TestPage;
web-app/src/App.js:
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
// ... import all pages
import { Provider } from 'react-redux';
import TestPage from './views/CreateSiteNeed'; // written same way for the other pages
import { store, FirebaseProvider } from 'common';
function App() {
return (
<Provider store={store}>
<FirebaseProvider>
<AuthLoading>
<Router history={hist}>
<Switch>
<ProtectedRoute exact component={MyProfile} path="/profile" />
<!-- [ ... ] more <ProtectedRoute /> lines, form imported Pages line 3. -->
<ProtectedRoute exact component={TestPage} path="/testpage" />
</Switch>
</Router>
</AuthLoading>
</FirebaseProvider>
</Provider>
);
}
export default App;
I hope some people will find this post helpful, thanks
Here was the problem :
Firstly :
I'm using Redux, so fetchTest() has its testActions.js and testReducer.js files, which are functionnal. But I did forget to update my store.js :
// [ ... ] import all reducers
import { testReducer as testData } from '../reducers/testReducer'; // was'nt imported
const reducers = combineReducers({
auth,
usersdata,
// [ ... ] other imported reducers
testData // My test reducer
}
// The rest is a classic store.js code
Secondly :
As I'm using Yarn Workspaces, I had to compile the code in common/dist/index.js to make it accessible through the whole entire code (even for local testing).
Here is the command to compile the code (-> to include all redux edits made above) and make it accessible to web-app workspace :
yarn workspace common build && yarn workspace web-app add common#1.0.0 --force
Explanations on the second part of the command (yarn workspace web-app add common#1.0.0 --force) :
The web-app/package.json file contains { "dependencies": { ... "common":"1.0.0" ... }}
I am trying to figure out how to add authentication to a react app that uses Cloud Firestore rather than Realtime Database.
I followed this tutorial and got the whole thing working. Then - the change I'm trying to add is the move from Realtime Database to Cloud Firestore - this makes a difference to whether authentication works. I have made 20 new projects to try to get this work - totally without the process in the tutorial and just relying on firebase documentation. None of them work.
Currently, I have a config file with:
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import firestore from "firebase/firestore";
class Firebase {
constructor() {
app.initializeApp(config).firestore();
this.auth = app.default.auth();
// this.db = app.firebase.database()
this.db = app.firestore();
}
Then, i have a form with this submit handler:
import Firebase from '../../../firebase.1';
handleCreate = () => {
const { form } = this.formRef.props;
form.validateFields((err, values) => {
if (err) {
return;
};
const payload = {
// ...values,
name: values.name,
email: values.email,
organisation: values.organisation,
beta: values.beta,
role: values.role,
// createdAt: Firebase.FieldValue.serverTimestamp()
}
console.log("formvalues", payload);
Firebase
.auth()
.createUserWithEmailAndPassword(values.email, values.password)
console.log('Received values of form: ', values);
Firebase
.collection("users")
.add(payload)
// .then(docRef => {
// resetForm(initialValues);
// })
.then(e => this.setState({ modalShow: true }))
form.resetFields();
this.setState({ visible: false });
this.props.history.push(DASHBOARD);
});
};
At the moment, when I console.log(Firebase) I get:
Uncaught ReferenceError: Firebase is not defined
I have seen this post and followed each one of the recommendations in all of the answers.
I have tried changing the config file uses:
this.auth = app.default.auth();
It makes no difference.
When I try to use this, i get an error that says:
TypeError: _firebase_1__WEBPACK_IMPORTED_MODULE_14__.default.auth is not a function
Does anyone know how to use auth with firebase - where there is a Cloud Firestore instead of a Realtime Database - it's so weird that this makes a difference to whether the authentication tool works.
I've turned off the timestamp entry because I can't get firestore to record that either - but that is a problem for another day. I'm really trying to figure out how to use the authentication tool for now.
NEXT ATTEMPT
I tried to change the firebase.js file so that the config now looks like this:
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const devConfig = {
};
const prodConfig = {
};
const config =
process.env.NODE_ENV === 'production' ? prodConfig : devConfig;
const Firebase = app.initializeApp(config);
const database = app.firestore();
const auth = app.auth();
const settings = { timestampsInSnapshots: true };
export { Firebase, database as default, settings, auth };
Now, I get an error that says:
TypeError: _components_firebase__WEBPACK_IMPORTED_MODULE_2__.default
is not a constructor
I have been googling - what is a constructor. What is a webpack imported module number reference etc for the last few hours. I would love to know how to translate these error messages into something understandable.
Googling this exact error message suggests that something is wrong with the way the import and export statements are made. The new export in firebase.js is unusual (but others on Stack Overflow have tried it with problems using Firebase). It's still a question mark for me because I don't understand what the error message means.
The error message points to this line of my src/index.js
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
That line comes from:
import FirebaseContext, { withFirebase } from './Context';
import Firebase from '../../firebase.1';
export default Firebase;
export { FirebaseContext, withFirebase };
That file imports from:
import React from 'react';
const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default FirebaseContext;
It would be a huge reveal if anyone has any advice for learning how to learn what error messages mean. For the moment I'm guessing.
I just finished the tutorial recently also, but I simplified my firebase file. I export only the reference to the initialised firebase
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const config = {
//...
};
const firebase = app.initializeApp(config);
export default firebase;
And in my project I have:
//...
import firebase from '../../firebase';
//...
useEffect(() => {
const listener = firebase
.firestore()
.collection(COLLECTIONS.USERS)
.onSnapshot(querySnapshot => {
setUsers(querySnapshot);
querySnapshot.forEach(doc => console.log(doc.id, doc.data()));
});
return listener;
}, []);
//...
Check out my Github project here -> https://github.com/henev/react-auth-with-firebase
I want to authenticate users w/ Twitter in my React Native app. I'm using the react-native-oauth library https://github.com/fullstackreact/react-native-oauth
I just want to make sure I'm going about this in the most effective way.
First things first I add firebase to my app in a config/constants file
import firebase from 'firebase'
firebase.initializeApp({
apiKey: "MY-API-KEY",
authDomain: "MY-AUTH-DOMAIN",
databaseURL: "MY-DATABASE-URL",
storageBucket: "MY-STORAGE-BUCKET",
messagingSenderId: "MY-MESSAGING-ID"
});
const ref = firebase.database().ref()
const firebaseAuth = firebase.auth()
export { ref, firebaseAuth }
Then I install the react-native-oauth library
Now, in my redux/authenticationI would probably do something like this where I eventually dispatch an action that saves the response object in my redux authentication state to use later.
import OAuthManager from 'react-native-oauth';
const manager = new OAuthManager('Nimbus') // I'm sort of confused on what the name of the app should be. Is it just the name of the app when I ran react-native init? Or something else?
export default function handleAuthWithFirebase () {
// Some redux thunk
return function (dispatch, getState) {
dispatch(authenticating());
manager.configure({
twitter: {
consumer_key: 'SOME_CONSUMER_KEY',
consumer_secret: 'SOME_CONSUMER_SECRET'
},
});
manager.authorize('twitter', {scopes: 'profile email'})
.then(resp => dispatch(getProfile(resp))) // Save response object
.catch(err => console.log('There was an error'));
// Do some other stuff like pushing a new route, etc.
}
}
Then finally, in SplashContainer.js I would add this to the handleSignIn method (ultimately called by the presentational component).
import React, { PropTypes, Component } from 'react'
import { View, Text } from 'react-native'
// Import function
import { handleAuthWithFirebase } from '~/redux/modules/authentication'
import { Splash } from '~/components'
export default class SplashContainer extends Component {
handleSignIn = () => {
// Sign in user with Twitter
handleAuthWithFirebase.bind(this);
}
render () {
return (
<Splash handleSignIn={this.handleSignIn}/>
)
}
}
Sorry, I know it was sort of a lot but just want to make sure I'm implementing this correctly. Any suggestions to improve the flow would be appreciated. Thanks!
can you check authenticate twitter with this package
https://github.com/GoldenOwlAsia/react-native-twitter-signin ?