'Cannot read property of undefined data() Firebase

I'm trying to implement redux saga in my old project and i get strange error. I'm getting back the userData with all user details but my middleware logger tells me that sign_in_failed fires instead of sign_in_success with this error:

Cannot read property of undefined data() Firebase.

So i tried to do optional chaining and i also tried the old way of deep property check (with &&) but this didnt help. Also, i cant anymore perform a stripe payments due to this error because stripe cant see the user.

UserSaga.jsx

import { takeLatest, all, call, put } from 'redux-saga/effects'
import { USER_ACTIONS_TYPES } from '../../actions/user/userActionsTypes'
import {
    signInSuccess,
    signInFailed,
    signUpSuccess,
    signUpFailed,
    signOutSuccess,
    signOutFailed
} from '../../actions/user/userActionCreator'
import {
    getCurrentUser,
    createUserDocumentFromAuth,
    createAuthUserWithEmailAndPassword,
    signInWithGooglePopup,
    signInAuthUserWithEmailAndPassword,
    signOutAuthUser
} from '../../../database/firebase.config'


export function* getUserSnapshot(userAuth, additionalInformation) {
    try {
        const userSnapshot = yield call(
            createUserDocumentFromAuth,
            userAuth,
            additionalInformation
        );
        
//yield put(signInSuccess({ id: userSnapshot?.id, ...userSnapshot.data()}));
  // console.log('userSnapshot2>>>>>>>>>', ...userSnapshot.data())

const id = userSnapshot?.id;
        const userData = userSnapshot.data()
        const {createdAt, email, password}= userData

        yield put(signInSuccess({ id, createdAt, email, password }));

        

        console.log('userSnapshot2>>>>>>>>>', userSnapshot)
    } catch (error) {
        yield put(signInFailed(error.message))

    }
}

export function* signInWithGoogle() {
    try {
        const { user } = yield call(signInWithGooglePopup)
        yield call(getUserSnapshot, user)
    } catch (error) {
        yield put(signInFailed(error))

    }
}


export function* signInWIthEmail({ payload: { email, password } }) {
    try {
        const { user } = yield call(signInAuthUserWithEmailAndPassword, email, password)
        yield call(getUserSnapshot, user)
    } catch (error) {
        yield put(signInFailed(error))
    }
}

export function* isUserAuth() {
    try {
        const userAuth = yield call(getCurrentUser)
        if (!userAuth) return;
        yield call(getUserSnapshot, userAuth)
    } catch (error) {
        yield put(signInFailed(error))
    }
}

export function* signUpWIthEmail({ payload: { email, password, displayName } }) {
    try {
        const { user } = yield call(createAuthUserWithEmailAndPassword, email, password)
        yield put(signUpSuccess(user, { displayName }))
    } catch (error) {
        yield put(signUpFailed(error))

    }
}

export function* signOut() {
    try {
        yield call(signOutAuthUser)
        yield put(signOutSuccess())
    } catch (error) {
        yield put(signOutFailed(error))
    }
}

export function* signInAfterSignUp({ payload: { user, additionalDetails } }) {
    yield call(getUserSnapshot, user, additionalDetails)
}

export function* onGoogleSignInStart() {
    yield takeLatest(USER_ACTIONS_TYPES.GOOGLE_SIGN_IN_START, signInWithGoogle)
}


export function* onCheckUserSession() {
    yield takeLatest(USER_ACTIONS_TYPES.CHECK_USER_SESSION, isUserAuth)

}

export function* onEmailSignInStart() {
    yield takeLatest(USER_ACTIONS_TYPES.EMAIL_SIGN_IN_START, signInWIthEmail)
}

export function* onSignUpStart() {
    yield takeLatest(USER_ACTIONS_TYPES.SIGN_UP_START, signUpWIthEmail)
}

export function* onSignUpSuccess() {
    yield takeLatest(USER_ACTIONS_TYPES.SIGN_IN_SUCCESS, signInAfterSignUp)
}

export function* onSignOutStart() {
    yield takeLatest(USER_ACTIONS_TYPES.SIGN_OUT_START, signOut)
}

export function* userSagas() {
    yield all([
        call(onCheckUserSession),
        call(onGoogleSignInStart),
        call(onEmailSignInStart),
        call(onSignUpStart),
        call(onSignUpSuccess),
        call(onSignOutStart),
        call(onSignUpSuccess)

    ])
}

firebase.config.js

// Initialize Firebase and Oauth
initializeApp(firebaseConfig);
const googleProvider = new GoogleAuthProvider();

googleProvider.setCustomParameters({
    prompt: "select_account"
})

//Initialize GAuth with popup signin method
export const auth = getAuth()
export const signInWithGooglePopup = () => signInWithPopup(auth, googleProvider)
    // export const signInWithGoogleRedirect = () => signInWithRedirect(auth, googleProvider)

// Initialize Firestore
export const db = getFirestore()

// get the conllection created with all docs
export const getCollectionWithDocuments = async() => {
    const collectionRef = collection(db, 'categories')
    const q = query(collectionRef)
    const querySnapShot = await getDocs(q)

    return querySnapShot.docs.map(docSnapshot => docSnapshot.data())

}

//Create a user document 
export const createUserDocumentFromAuth = async(userAuth, additionalInformation = {}) => {
    if (!userAuth) return;

    const userDocRef = doc(db, 'users', userAuth.uid)

    // console.log('userRef>>', userDocRef)

    const userSnapshot = await getDoc(userDocRef)
        // console.log('just snapshot>>>', snapShot)
        // console.log('if shot exist>>', snapShot.exists())

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

        try {
            await setDoc(userDocRef, {
                displayName,
                email,
                createdAt,
                ...additionalInformation

            })
        } catch (error) {
            console.log("error creating user", error.message)
        }
    }
    return userSnapshot;

}

export const createAuthUserWithEmailAndPassword = async(email, password) => {
    if (!email || !password) return;

    return await createUserWithEmailAndPassword(auth, email, password)

}


export const signInAuthUserWithEmailAndPassword = async(email, password) => {
    if (!email || !password) return;

    return await signInWithEmailAndPassword(auth, email, password)

}

export const signOutAuthUser = async() => await signOut(auth)

export const onAuthObserver = (callback) => onAuthStateChanged(auth, callback)


//Create a collection of document in firestore (call it ones inside useeffect to avoid mutations)
export const createCollectionWithDocuments = async(collectionName, objectsToAdd) => {
    const collectionRef = collection(db, collectionName)
    const batch = writeBatch(db)

    objectsToAdd.forEach(object => {
        const docRef = doc(collectionRef, object.title.toLowerCase())
        batch.set(docRef, object)
    })
    await batch.commit()
    console.log('collection created')
}



export const getCurrentUser = () => {
    return new Promise((resolve, reject) => {
        const unsubscribe = onAuthStateChanged(
            auth,
            (userAuth) => {
                unsubscribe();
                resolve(userAuth);
                // console.log(userAuth)
            },
            reject)
    })
}

userReducer.jsx

export const INITIAL_STATE = {
    currentUser: null,
    isLoading: false,
    error: null
}

export const userReducer = (state = INITIAL_STATE, action) => {
    const { type, payload } = action;

    switch (type) {
        case USER_ACTIONS_TYPES.SIGN_IN_SUCCESS:
            return {
                ...state,
                currentUser: payload,
                error: null
            }
        case USER_ACTIONS_TYPES.SIGN_OUT_SUCCESS:
            return {
                ...state,
                currentUser: null
            }
        case USER_ACTIONS_TYPES.SIGN_OUT_FAILED:
        case USER_ACTIONS_TYPES.SIGN_UP_FAILED:
        case USER_ACTIONS_TYPES.SIGN_IN_FAILED:
            return {
                ...state,
                error: payload
            }
        default:
            return state
    }
}

userActions.js

export const emailSignInStart = (email, password) => createActions(USER_ACTIONS_TYPES.EMAIL_SIGN_IN_START, { email, password })

export const signInSuccess = user => createActions(USER_ACTIONS_TYPES.SIGN_IN_SUCCESS, user)

export const signInFailed = error => createActions(USER_ACTIONS_TYPES.SIGN_IN_FAILED, error)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source