Home > database >  Firebase createUserProfileDocument() is returning undefined
Firebase createUserProfileDocument() is returning undefined

Time:03-07

the createUserProfileDocument() method from firebase is returning undefined for some reason, therefore, it's throwing an error on my broswer's console.

The error thrown is:

App.js:23 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'onSnapshot') at App.js:23:1

the code:

import React from 'react';
import './App.css';
import { connect } from 'react-redux';
import { Switch, Route } from 'react-router-dom';
import HomePage from './pages/homepage/homepage.component';
import ShopPage from './pages/shop/shop.component';
import Header from './components/header/header.componet';

import { auth, createUserProfileDocument } from './firebase/firebase.utils';
import SignInAndSignUpPage from './pages/sign-in-and-sign-up/sign-in-and-sign-up.component';
import { setCurrentUser } from './redux/user/user.actions';

class App extends React.Component {
    unsubscribeFromAuth = null;

    componentDidMount() {
        const { setCurrentUser } = this.props;

        this.unsubscribeFromAuth = auth.onAuthStateChanged(async (userAuth) => {
            if (userAuth) {
                const userRef = await createUserProfileDocument(userAuth);
                console.log(userRef);
                userRef.onSnapshot((snapshot) => {
                    setCurrentUser({
                        id: snapshot.id,
                        ...snapshot.data(),
                    });
                });
            }
            setCurrentUser(userAuth);
        });
    }

    componentWillUnmount() {
        this.unsubscribeFromAuth();
    }

    render() {
        return (
            <div className='App'>
                <Header />
                <Switch>
                    <Route exact path='/' component={HomePage} />
                    <Route exact path='/shop' component={ShopPage} />
                    <Route
                        exact
                        path='/signin'
                        component={SignInAndSignUpPage}
                    />
                </Switch>
            </div>
        );
    }
}

const mapDispatchToProps = (dispatch) => ({
    setCurrentUser: (user) => dispatch(setCurrentUser(user)),
});

export default connect(null, mapDispatchToProps)(App);

The portion of code related to my error is the following:

componentDidMount() {
        const { setCurrentUser } = this.props;

        this.unsubscribeFromAuth = auth.onAuthStateChanged(async (userAuth) => {
            if (userAuth) {
                const userRef = await createUserProfileDocument(userAuth);
                console.log(userRef);
                userRef.onSnapshot((snapshot) => {  // This is Line 23......
                    setCurrentUser({
                        id: snapshot.id,
                        ...snapshot.data(),
                    });
                });
            }
            setCurrentUser(userAuth);
        });
    }

I console.logged(userRef) as you can see, and it returns undefined. This is my first experience with firebase so I am not sure where the error is.

I googled and found an answer here in stackoverflow which is alike to my issue: TypeError: Cannot read properties of undefined (reading 'onSnapshot')

However, that problem is specifically related to how the developer was passing the method as an array and not a method, which does not help my situation.

EDIT: Adding firebase.utils code.

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import 'firebase/compat/auth';

const config = {
  apiKey: 'AIzaSyDxUMY8sUpOMAoxEyHo41ONilzjL2woWHk',
  authDomain: 'crown-db-d4416.firebaseapp.com',
  projectId: 'crown-db-d4416',
  storageBucket: 'crown-db-d4416.appspot.com',
  messagingSenderId: '887003208895',
  appId: '1:887003208895:web:778f8f55a0ad2c72953a0a',
  measurementId: 'G-6TGCRVN7D3',
};

export const createUserProfileDocument = async (userAuth, additionalData) => {
  if (!userAuth) return;

  const userRef = firestore.doc(`users/${userAuth.uid}`);
  const snapShot = await userRef.get();

  console.log(snapShot);
  if (!snapShot.exists) {
    const { displayName, email } = userAuth;
    const createdAt = new Date();

    try {
      await userRef.set({
        displayName,
        email,
        createdAt,
        ...additionalData,
      });
    } catch (error) {
      console.log('Error creating user: ', error.message);
    }
  }
};

firebase.initializeApp(config);

export const auth = firebase.auth();
export const firestore = firebase.firestore();

const googleProvider = new firebase.auth.GoogleAuthProvider();
export const signInWithGoogle = () => {
  auth
    .signInWithPopup(googleProvider)
    .then((res) => {
      console.log(res.user);
    })
    .catch((error) => {
      console.log(error.message);
    });
};

export default firebase;

CodePudding user response:

Your createUserProfileDocument function doesn't return anything, so that explains why this code then fails:

const userRef = await createUserProfileDocument(userAuth);
console.log(userRef);
userRef.onSnapshot((snapshot) => {

The solution is to return the userRef from createUserProfileDocument as your calling code expects:

export const createUserProfileDocument = async (userAuth, additionalData) => {
  ...
  return userRef;
};
  • Related