0

I'm currently working on a React / Redux / Firebase application.

In my Firebase Cloud Firestore I store user data, dynamically created after creating an Auth user.

In my index.js I use useFirestoreForProfile: true to get the corresponding user data to show up in firebase.profile

index.js

const store = createStore(rootReducer,
    compose(
        applyMiddleware(
            thunk.withExtraArgument({
                getFirebase, // Firebase
                getFirestore // Cloud Database
            })
        ),
        reduxFirestore(fbInit),
        reactReduxFirebase(fbInit, {
            useFirestoreForProfile: true, // Sync user data to firebase.profile
            userProfile: 'users', // Tell Redux Firebase where our users are stored
            attachAuthIsReady: true // Enable firebase initializing before DOM rendering
        })
    )
);

My authentication action:

/store/actions/authActions.js

export const signIn = (credentials) => {
    return (dispatch, getState, {getFirebase}) => {
        const firebase = getFirebase();

        firebase.auth().signInWithEmailAndPassword(
            credentials.email,
            credentials.password
        ).then(() => {
            dispatch({
                type: 'LOGIN_SUCCESS'
            })
        }).catch((err) => {
            dispatch({
                type: 'LOGIN_ERROR',
                err
            })
        });
    }
}

The part of successful login in my authentication reducer:

/store/reducers/authReducer.js

  case 'LOGIN_SUCCESS':
      console.log('Login success');
      return {
         ...state,
         authError: null,
         authErrorDetails: null
      };

The way I map the state to the component props:

/components/pages/Dashboard/index.jsx

const mapStateToProps = (state) => {
    console.log(state);
    return {
        records: state.firestore.ordered.records,
        tabs: state.firestore.ordered.tabs,
        auth: state.firebase.auth,
        profile: state.firebase.profile
    }
}

The current profile data looks like this:

Profile data

Within the user document where those fields are set, I've created an additional collection.

The path would look as: users -> (document id) -> tabs -> (document id) -> fields

Database structure

Is there any way to include the tabs collections in firebase.profile


The final object should look something like the one I just created manually for displaying purposes:

Desired structure

Is there a way of achieving this? I really hope it's only a param missing or something.

4

2 回答 2

0

Any read operation to Firestore returns documents from a single collection (or if you use collection group queries) from collections with the same name. There is no way to deeply query nested collections like you have in your data model. In your model you will need separate read operations for the documents from users and those from tabs.

Beyond that it's hard to say what specifically you will have to do, as I don't know what useFirestoreForProfile is and what the profile object you show represents.

于 2019-07-21T20:19:42.237 回答
0

I have solved the problem by creating an array within the user fields.

export const createTab = (tab) => {
    return (dispatch, getState, { getFirebase, getFirestore }) => {
        // Make aync call to DB

        // Get userId (to know where to store the new tab)
        const userId = getState().firebase.auth.uid;
        // Get user tabSlots to decide how many tabs the user may have
        const userTabSlots = getState().firebase.profile.tabSlots;
        // Get current tabs (to not overwrite)
        const currentTabs = getState().firebase.profile.tabs;

        // Check if already exists
        let exists = currentTabs.map((ctab, i) => {
            if(ctab.title === tab.title){
                dispatch({ type: 'CREATE_TAB_ERROR_DUPLICATE', err: "Duplicate" });
                return true;
            } else {
                return false;
            }
        });

        // Check if the user can make new tabs dependent on the tier
        let canCreate = true;
        if(currentTabs.length === userTabSlots){
            dispatch({ type: 'CREATE_TAB_ERROR_LIMIT', err: "Tab limit reached" });
            canCreate = false;
        }

        // If it does not already exists and user can create new tabs
        if(!exists.includes(true) && canCreate){
            const firestore = getFirestore();
            firestore.collection('users').doc(userId).update({
                tabs: [
                    ...currentTabs,
                    {...tab, createdAt: new Date()} 
                ]
            }).then(() => {
                dispatch({ type: 'CREATE_TAB', tab });
            }).catch((err) => {
                dispatch({ type: 'CREATE_TAB_ERROR', err });
            })
        }
    }
}
于 2019-07-23T23:29:21.613 回答