Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getFirebase(...).firestore(...).set is not a function -- how to make firestore work inside action like v2 please help! #839

Open
knour89 opened this issue Jan 20, 2020 · 25 comments

Comments

@knour89
Copy link

knour89 commented Jan 20, 2020

as we know from V3 no more getFirestore() it should be replaced with getFirebase().firestore() - but it's not working and give me below message getFirebase(...).firestore(...).set is not a function

here is my action

export const registerUser = data => async (dispatch, getState, getFirebase) => {
  const firebase = getFirebase();
  const firestore = getFirebase().firestore();
  try {
    let createdUser = await firebase
      .auth()
      .createUserWithEmailAndPassword(data.email, data.password);

    await createdUser.user.updateProfile({
      displayName: data.displayName
    });

    await firestore.set(`users/${createdUser.user.uid}`, {
      displayName: data.displayName,
      createdAt: firestore.FieldValue.serverTimestamp()
    });
}catch(error){}

here my configure store

import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { getFirebase } from "react-redux-firebase";

import thunk from "redux-thunk";
import rootReducer from "../reducers/rootReducer";

export const configureStore = () => {
  const middlewares = [thunk.withExtraArgument(getFirebase)];

  const composeEnhancers = composeWithDevTools(applyMiddleware(...middlewares));

  const store = createStore(rootReducer, composeEnhancers);
  return store;
};

@knour89 knour89 changed the title getFirebase(...).firestore(...).set is not a function -- how to make firestore work inside action like vs please help getFirebase(...).firestore(...).set is not a function -- how to make firestore work inside action like v2 please help! Jan 20, 2020
@prescottprue
Copy link
Owner

Main Issue

If firestore.set is not available It may be due to not having imported Firestore - what do the imports look like along side your main initializeApp? Also, would help to include your app setup.

In the next section I describe how there is built in logic for doing what you seem to be writing logic for:

A Built In Way To Do Similar

Something to note: the functionality that you are trying to write (i.e a profile written to users/${uid}) is supported by default if you pass the following in your config:

{
  userProfile: 'users',
  useFirestoreForProfile: true // store profiles in Firestore instead of RTDB
  // updateProfileOnLogin: false // add if you don't want profile updated on every login
  /* Add to change how profiles are stored in database:
  profileFactory: (userData, profileData, firebase) => {
    const { user } = userData
    return {
      email: user.email
    }
  } */
}

This is also described in the profile recipes within the docs.

Then when you call firebase.login() or firebase.createUser the profile is automatically written to Firestore. If you would like to change the format of how the profile is written you can provide the profileFactory config.

If you need to call anything after (like updateProfile) you can do that after the login promise completes:

const { email, password, displayName } = data
const createdUser = await firebase.login({ email, password }, { email, displayName })
await createdUser.user.updateProfile({ displayName });

@knour89
Copy link
Author

knour89 commented Jan 24, 2020

hello here is my settings:

const rrfProps = { firebase, config: { userProfile: "users", useFirestoreForProfile: true, updateProfileOnLogin: false }, dispatch: store.dispatch, createFirestoreInstance };

and firebase config
`const firebaseConfig = {
apiKey: " ",
authDomain: " ",
databaseURL: " ",
projectId: "r ",
storageBucket: "r ",
messagingSenderId: " ",
appId: "1 ",
measurementId: ""
};

firebase.initializeApp(firebaseConfig);
firebase.firestore();

export default firebase;`

My question how to user firestore inside action, can you give me example? becouse firebase().firstore is not working

@prescottprue
Copy link
Owner

I am not seeing any imports in your example, are you sure you are importing Firestore? Could you provide a full repo where this can be reproduced?

Based on your settings, as I noted above, you should be able to do the following without creating a separate custom action:

const { email, password, displayName } = data
const createdUser = await firebase.login({ email, password }, { email, displayName })
await createdUser.user.updateProfile({ displayName })

@eliasnorrby
Copy link

I believe I am having the same problem. I believe I have set everything up
according to the instructions (I'll summarize below).

  1. I've initialized firebase & firebase.firestore()
  2. I've passed getFirebase as an extra argument to redux-thunk
  3. I've added the appropriate reducers to my rootReducer
  4. I've wrapped my app in react-redux's Provider and in ReactReduxFirebaseProvider

In my components, I can successfully use hooks (useFirebase, useFirestore) to
get the corresponding instances.

In my thunk actions, I can use getFirebase() to get the firebase instance, but
getFirebase().firestore() does not give me the firestore instance. Or at least,
that's what I've assumed from primitive console.log inspection. In a component,
all methods (including set) are available, whereas in the thunk they are not.

Comparison:

// in a component
const firestore = useFirestore()
console.log(firestore)

// output
{
  blob: function PublicConstructor()
  CACHE_SIZE_UNLIMITED: -1
  CollectionReference: function PublicConstructor()DocumentReference: function PublicConstructor()DocumentSnapshot: function PublicConstructor()FieldPath: function FieldPath$1()FieldValue: function PublicConstructor()Firestore: function PublicConstructor()GeoPoint: function GeoPoint(latitude, longitude)Query: function PublicConstructor()QueryDocumentSnapshot: function PublicConstructor()QuerySnapshot: function PublicConstructor()Timestamp: function Timestamp(seconds, nanoseconds)Transaction: function PublicConstructor()WriteBatch: function PublicConstructor()_: Object ... ,
  add: function createWithFirebaseAndDispatch()batch: function ()
  collection: function ()
  collectionGroup: function ()
  configureClient: function ()
  default: function createWithFirebaseAndDispatch()delete: function createWithFirebaseAndDispatch()deleteRef: function createWithFirebaseAndDispatch()disableNetwork: function ()
  doc: function ()
  enableNetwork: function ()
  enablePersistence: function ()
  ensureClientConfigured: function ()
  get: function createWithFirebaseAndDispatch()onSnapshot: function createWithFirebaseAndDispatch()runTransaction: function createWithFirebaseAndDispatch()set: function createWithFirebaseAndDispatch()setListener: function createWithFirebaseAndDispatch()setListeners: function createWithFirebaseAndDispatch()setLogLevel: function setLogLevel(level)settings: function ()
  unsetListener: function createWithFirebaseAndDispatch()unsetListeners: function createWithFirebaseAndDispatch()update: function createWithFirebaseAndDispatch()
}
// in a thunk
const firebase = getFirebase()
const firestore = firebase.firestore()
console.log(firestore)

// output
{
  INTERNAL: Object ... ,
  _credentials: Object ... ,
  _dataConverter: Object ... ,
  _databaseId: Object ... ,
  _firebaseApp: Object ... ,
  _firestoreClient: Object ... ,
  _persistenceKey: "[DEFAULT]"
  _queue: Object ... ,
  _settings: Object ... ,
}

Any idea what is up? I can provide a complete repo/sandbox given the time if it helps.

@prescottprue
Copy link
Owner

A full repro in codesandbox would be good - The usage of the new context API changes how gathering the extended firebase instance works.

@eliasnorrby
Copy link

eliasnorrby commented Jan 30, 2020

Okay, here's an example: https://codesandbox.io/s/rrf-bug-repro-839-nret4

It started pretty minimal but grew when I wanted to test different cases, I hope there's not too much fluff. The demo just fetches a document from firestore in different contexts (component vs thunk), using different apis (base vs extended) and different ways of acquiring the firestore instance (firebase.firestore() vs useFirestore()). Here's a summary:

In a component:

  • useFirebase().firestore().get(..) : broken
  • useFirebase().firestore().collection(..).doc(..).get() : works
  • useFirestore().get(..) : works
  • useFirestore().collection(..).doc(..).get() : works

In a thunk:

  • getFirebase().firestore().get(..) : broken
  • getFirebase().firestore().collection(..).doc(..).get() : works

So, in short, the extended firestore api doesn't seem to be available when using firebase.firestore().

@knour89
Copy link
Author

knour89 commented Feb 2, 2020

I am not seeing any imports in your example, are you sure you are importing Firestore? Could you provide a full repo where this can be reproduced?

Based on your settings, as I noted above, you should be able to do the following without creating a separate custom action:

const { email, password, displayName } = data
const createdUser = await firebase.login({ email, password }, { email, displayName })
await createdUser.user.updateProfile({ displayName })

can u please create an example how to use firestore inside actions?

@knour89
Copy link
Author

knour89 commented Feb 2, 2020

again here is my codes:
Firebase.js

 import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/auth";
import "firebase/storage";
import "firebase/database";

const firebaseConfig = {
 secrets
};

firebase.initializeApp(firebaseConfig);
firebase.firestore();

export default firebase;

Configure Store:

import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { getFirebase } from "react-redux-firebase";

import thunk from "redux-thunk";
import rootReducer from "../reducers/rootReducer";

export const configureStore = () => {
  const middlewares = [thunk.withExtraArgument(getFirebase)];

  const composeEnhancers = composeWithDevTools(applyMiddleware(...middlewares));

  const store = createStore(rootReducer, composeEnhancers);
  return store;
};

root reducer:

import { combineReducers } from "redux";
import { reducer as FormReducer } from "redux-form";
import { reducer as toastrReducer } from "react-redux-toastr";
import eventReducer from "../../features/event/eventReducer";
import ModalReducer from "../../features/Modals/ModalReducer";
import AuthReducers from "../../features/auth/AuthReducers";
import AsyncReducers from "../../features/async/AsyncReducers";
import { firebaseReducer } from "react-redux-firebase";
import { firestoreReducer } from "redux-firestore";

export default combineReducers({
  firebase: firebaseReducer,
  firestore: firestoreReducer,
  form: FormReducer,
  toastr: toastrReducer,
  auth: AuthReducers,
  events: eventReducer,
  modals: ModalReducer,
  async: AsyncReducers
});

index,js


import firebase from "./app/config/firebase";
import { Provider } from "react-redux";
import { ReactReduxFirebaseProvider } from "react-redux-firebase";
import { createFirestoreInstance } from "redux-firestore";
import { BrowserRouter } from "react-router-dom";
import { configureStore } from "./app/store/configureStore";


const store = configureStore();
const rrfProps = {
  firebase,
  config: {
    userProfile: "users",
    useFirestoreForProfile: true,
    updateProfileOnLogin: false
  },
  dispatch: store.dispatch,
  createFirestoreInstance
};

let render = () => {
  ReactDOM.render(
    <Provider store={store}>
      <ReactReduxFirebaseProvider {...rrfProps}>
        <BrowserRouter>
          <AuthIsLoaded>
            <ScrollToTop />
            <ReduxToastr
              timeOut={3000}
              position="bottom-right"
              transitionIn="bounceIn"
              transitionOut="bounceOut"
            />
            <App />
          </AuthIsLoaded>
        </BrowserRouter>
      </ReactReduxFirebaseProvider>
    </Provider>,
    rootEl
  );
};

and until now cant use getFirebase().firestore()

@prescottprue
Copy link
Owner

Has anyone tried using getFirestore from redux-firestore?

@eliasnorrby
Copy link

Yes, that's where I started. I've added that option to the sandbox. Calling getFirestore in the thunk gives me the error:

Firebase instance does not yet exist. Check your compose function.

@knour89
Copy link
Author

knour89 commented Feb 9, 2020

help please, I did turn around = I used withFirestore & withFirebase as hoc then pass it aas urgmenets to action but this is alot of code here

export default compose(
  withFirestore,
  withFirebase,
  connect(mapStateToProps, { createEvent, updateEvent, cancelToggle }),
  reduxForm({ form: "eventForm", enableReinitialize: true, validate })
)(EventForm);

@deepankar14693
Copy link

@knour89 did you find any solution, because I'm also stuck with the same?

@deepankar14693
Copy link

deepankar14693 commented Feb 20, 2020

@knour89 : Here is the solution of your exact problem. Instead of calling
await firebase.set(users/${createdUser.user.uid}, { ...newUser }) from action creator try the given below function from registerForm, you just have to import from {withFirestore} from react-redux-firebase and use it as a HOC in RegisterFormComponent. It works for me because I was stuck in the same problem.
Feel free to ask if below code is not clear:

onFormSubmit = async (values) => {
    try {
      await this.props.registerUser(values);
      let newUser = {
        displayName: values.displayName,
        createdAt: this.props.firestore.FieldValue.serverTimestamp()
      }
      const uid = this.props.uid;
      await this.props.firestore.set(`users/${uid}`, { ...newUser })
      this.props.closeModal();
    }
    catch (err) {
      console.log(err)
    }
  }

@eliasnorrby
Copy link

@deepankar14693 : That surely works, but the issue here is specifically related to using firestore in a redux thunk. We don't want to call firestore.set within a onClick or onFormSubmit handler, but within a thunk, i.e.

/* component.js */
onFormSubmit = (values) => dispatch(registerUser(values))

/* some-thunk.js */
registerUser = (values) => async (dispatch, getState, { getFirebase }) => {
  const firestore = getFirebase().firestore()
  firestore.set(/* ... */)
}

The workaround for now seems to be to get hold of the firestore instance within the component (using either the hooks or the HOC API) and pass it along in the action creator.

/* component.js */
const  firestore = useFirestore()
/* ... */
onFormSubmit = (values) => dispatch(registerUser(values, firestore))

/* some-thunk.js */
registerUser = (values, firestore) => async (dispatch, getState) => {
  firestore.set(/* ... */)
}

@hemantkumar5151
Copy link

TypeError: getFireStore is not a function when pass argument in action creator.

firebase.js
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';

var firebaseConfig = {
secretKey
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.firestore()

export default firebase;

Root.jsx
import { combineReducers } from 'redux';
import authReducer from './reducers/authReducer';
import projectReducer from './reducers/projectReducer';

const rootReducers = combineReducers({
auth: authReducer,
project: projectReducer,
})
export default rootReducers;

store..jsx

import {createStore } from 'redux';
import { applyMiddleware, compose } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import { reduxFirestore, getFirestore } from 'redux-firestore';
import { reactReduxFirebase, getFirebase, } from 'react-redux-firebase';
import firebase from '../config/firebase';
import rootReducers from './root';
const middlewares = [logger, thunk.withExtraArgument({getFirebase, getFirestore})]

const store = createStore(rootReducers,compose(
reactReduxFirebase(firebase),
reduxFirestore(firebase),
applyMiddleware(...middlewares)
))
export default store;

projectReducer.jsx

const INITIAL_STATE = {
projects: [
{id: 1, title: 'The Singh is King', content: 'This is book about man power'},
{id: 2, title: 'The Singh is King', content: 'This is book about man power'}
]
};

const projectReducer = (state = INITIAL_STATE, action) => {
switch(action.type ) {
case 'CREATE_PROJECT':
console.log('created project', action.project)
return state
case 'CREATE_PROJECT_ERROR':
console.log('Error in project created', action.type);
return state

    default:
        return state
}

}
export default projectReducer;

projectAction.jsx

export const createProject = (project) => {
return (dispatch, getState, {getFirebase, getFireStore} ) => {

    const firestore = getFireStore();
    firestore.collection('projects').add({
        ...project,
        authorFirstname: 'Robin',
        authorLastname: 'Kumar',
        author: 12121,
        createdAt: new Date()
    }).then(()=>{
        dispatch({ type: 'CREATE_PROJECT', project })
    }).catch(err=>{
        dispatch({type: 'CREATE_PROJECT_ERROR', err})
    })       
}

}

@deepankar14693
Copy link

@eliasnorrby I was just trying to help @knour89 out so that he can move on with further development and not just get stuck.
I tried finding the solution to use getFirestore in redux-thunk but currently I'm unable to do so.
If you have found out the answer, please let me know I'll be highly thankful to you.

@eliasnorrby
Copy link

@deepankar14693 Yes, of course, it's just that from @knour89 's latest comment it seemed he was using a workaround involving withFirestore already, so I was a little confused as to what you meant. 😄

Haven't found a solution yet, but I'll let you know if I do. Likewise to you – if you find one I'd be very grateful to know. 🙏

@deepankar14693
Copy link

deepankar14693 commented Feb 26, 2020

@eliasnorrby what about createFirestoreInstance which is imported from redux-firestore and passed as props to ReactReduxFirebaseProvider. Infact it takes firebase as parameter and in return gives a firestore instance.
Time for some R&D......

@makannew
Copy link

makannew commented Mar 6, 2020

@knour89
Hi,

I find that when firestore instance created by firebase.firestore() we don't have access to "set", because it is not a native firestore method, you can change your code like this:

const firestore = firebase.firestore();
await firestore.collection("users").doc(createdUser.user.uid).set({yourProperties})

In addition of "set" there are other methods such as "get, add, update, delete ,..." which they are available through getFirestore(). For more information you can check reduxFirestore enhancer

If you still need those enhanced capabilities you can set thunk to pass down getFirestore like this:

import { createStore, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { getFirestore, reduxFirestore } from "redux-firestore";
import { getFirebase } from "react-redux-firebase";
import firebase from "../config/fb-config";
import { createFirestoreInstance } from "redux-firestore";

import rootReducer from "./reducers/root-reducer";

const rrfConfig = {
  userProfile: "users",
  useFirestoreForProfile: true,
  enableClaims: true
};

const initialState = {};
const middlewares = [thunk.withExtraArgument({ getFirebase, getFirestore })]; 
const store = createStore(
  rootReducer,
  initialState,
  compose(applyMiddleware(...middlewares), reduxFirestore(firebase, rrfConfig))
);

export const rrfProps = {
  firebase,
  config: rrfConfig,
  dispatch: store.dispatch,
  createFirestoreInstance
};

export default store;

Then in your action you can access to enhanced firestore instance by provoking getFirestore().

export const createDoc = newDoc => {
  return async (dispatch, getState, { getFirebase, getFirestore }) => {
  const firestoreEnhanced = getFirestore(); // with additional methods like set, get,..
  const firestoreOrginal = getFirebase.firestore(); // not enhanced, set method is not available
 
}

Hopefully it is related to what you actually need and solves your problem.

@agiguere
Copy link

agiguere commented Sep 9, 2020

@deepankar14693 Yes, of course, it's just that from @knour89 's latest comment it seemed he was using a workaround involving withFirestore already, so I was a little confused as to what you meant. 😄

Haven't found a solution yet, but I'll let you know if I do. Likewise to you – if you find one I'd be very grateful to know. 🙏

Have you found a solution? I am having a similar issue but I am using the redux toolkit, all HOC functions and hooks works fine, but passing the getFirebase & getFirestore to thunk failed, it says Firebase not defined ...

according to the doc, store enhancers are deprecated in V3 in favor of the React context API, looks like the API documentation is not up to date for Thunk in V3

thanks

@eliasnorrby
Copy link

@agiguere Haven't been working on the related project for some months. Not really up to date on whether there has been any updates to react redux firebase to solve it, but the workaround I described in a previous comment should still work, I guess.

Since (like you're saying) the hooks work, you can get hold of the firebase or firestore instance in the component using useFirebase() or useFirestore() and pass them as an argument to your action handler.

@Jsh007
Copy link

Jsh007 commented Sep 18, 2020

@deepankar14693 : That surely works, but the issue here is specifically related to using firestore in a redux thunk. We don't want to call firestore.set within a onClick or onFormSubmit handler, but within a thunk, i.e.

/* component.js */
onFormSubmit = (values) => dispatch(registerUser(values))

/* some-thunk.js */
registerUser = (values) => async (dispatch, getState, { getFirebase }) => {
  const firestore = getFirebase().firestore()
  firestore.set(/* ... */)
}

The workaround for now seems to be to get hold of the firestore instance within the component (using either the hooks or the HOC API) and pass it along in the action creator.

/* component.js */
const  firestore = useFirestore()
/* ... */
onFormSubmit = (values) => dispatch(registerUser(values, firestore))

/* some-thunk.js */
registerUser = (values, firestore) => async (dispatch, getState) => {
  firestore.set(/* ... */)
}

Cool !
However, I'm getting a duplicate Firebase App warning. Doesn't that create
security loopholes and how do I solve it?

duplicate_fbApp

@prescottprue
Copy link
Owner

@Jsh007 I believe that is coming from initializeApp being called multiple times - this can happen in development easily due to module reloading - Try only initializing if the instance doesn't exist or putting a try/catch around the call to initializeApp

@Jsh007
Copy link

Jsh007 commented Oct 4, 2020

@prescottprue Thank you. I'm still unable to access getFirestore and getFirebase in my thunk action creators. Presently, I'm creating an instance of useFirestore and UseFirbase in my Ui components and passing It along with payload to my thunk action creators and it is making my App unstable. Since I became comfortable with reduxToolkit; I have come to love it. I now find vanilla redux unnecessarily verbose and unusable. I'm using ReduxToolkit with configureStore. RRF is a great tool, but please could you see why getFirestore and getFirebase aren't passing through to thunk action creators when using configureStore?

My store; store.js

import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import {
  getFirestore,
  firestoreReducer,
  constants as rfConstants,
} from "redux-firestore";
import {
  getFirebase,
  firebaseReducer,
  actionTypes as rrfActionTypes,
} from "react-redux-firebase";
import auth from "../features/auth/authSlice";

const reducer = {
  auth,
  firebase: firebaseReducer,
  firestore: firestoreReducer,
};
const extraArgument = {
  getFirebase,
  getFirestore,
};
const middleware = [
  ...getDefaultMiddleware({
    serializableCheck: {
      ignoredActions: [
        // just ignore these
        ...Object.keys(rfConstants.actionTypes).map(
          (type) => `${rfConstants.actionsPrefix}/${type}`
        ),
        ...Object.keys(rrfActionTypes).map(
          (type) => `@@reactReduxFirebase/${type}`
        ),
      ],
      ignoredPaths: ["auth", "firebase", "firestore"],
    },
    thunk: {
      extraArgument,
    },
  }),
];

const preLoadedState = {};
const Store = configureStore({
  reducer,
  middleware,
  devTools: true,
  preLoadedState,
  enhancers: (defaultEnhancers) => [...defaultEnhancers],
});

export default Store;

My App.js

import React, { useState, useEffect } from "react";
import { NavigationContainer } from "@react-navigation/native";
import Navigation from "./features/navigation/Navigation";
import { Provider } from "react-redux";
import Store from "./store/Store";
import {
  ReactReduxFirebaseProvider,
  createFirebaseInstance,
} from "react-redux-firebase";
import { createFirestoreInstance } from "redux-firestore";
import firebase from "./config/fbConfig";
if (__DEV__) {
  import("./ReactotronConfig");
}
import Reactotron from "reactotron-react-native";
import { YellowBox } from "react-native";
// UI kitten
import * as eva from "@eva-design/eva";
import { ApplicationProvider } from "@ui-kitten/components";

//HIDE YELLOW BOX
YellowBox.ignoreWarnings(["Setting a timer"]);

// Reactotron.log("Awake !");

// PRELOAD ASSETS
import { AppLoading } from "expo";
import { Asset } from "expo-asset";
import * as Font from "expo-font";

// ASSETS LOADER
function cacheImages(images) {
  return images.map((image) => {
    if (typeof image === "string") {
      return Image.prefetch(image);
    } else {
      return Asset.fromModule(image).downloadAsync();
    }
  });
}

function cacheFonts(fonts) {
  return fonts.map((font) => Font.loadAsync(font));
}

export default function App() {
  // INIT ASSETS LOAD STATE

  const [isReady, setisReady] = useState(false);

  const _loadAssetsAsync = async () => {
    const imageAssets = cacheImages([
      require("./assets/images/Rantapp-Slogo.png"),
      require("./assets/images/Rantapp-txt.png"),
      require("./assets/images/josh9.jpeg"),
    ]);

    const fontAssets = cacheFonts([
      { "OpenSans-Regular": require("./assets/font/OpenSans-Regular.ttf") },
      { "OpenSans-Bold": require("./assets/font/OpenSans-Bold.ttf") },
      { "OpenSans-Light": require("./assets/font/OpenSans-Light.ttf") },
    ]);

    await Promise.all([...imageAssets, ...fontAssets]);
  };

  if (!isReady) {
    return (
      <AppLoading
        startAsync={_loadAssetsAsync}
        onFinish={() => setisReady(true)}
        onError={console.warn}
      />
    );
  }

  // react-redux-firebase config
  const rrfConfig = {
    userProfile: "users",
    enableClaims: true,
    useFirestoreForProfile: true,
  };

  // React-redux-firebase props
  const rrfProps = {
    firebase,
    config: rrfConfig,
    dispatch: Store.dispatch,
    createFirestoreInstance,
  };

  return (
    <Provider store={Store}>
      <ReactReduxFirebaseProvider {...rrfProps}>
        <NavigationContainer>
          <ApplicationProvider {...eva} theme={eva.light}>
            <Navigation />
          </ApplicationProvider>
        </NavigationContainer>
      </ReactReduxFirebaseProvider>
    </Provider>
  );
}

my RTK slice (authSlice.js)

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

const authSlice = createSlice({
  name: "auth",
  initialState: {
    loading: "idle",
    authError: null,
  },
  reducers: {
    processStarted: (state, action) => {
      if (state.loading === "idle") {
        state.loading = "pending";
      }
      state.authError = null;
    },
    processCompleted: (state, action) => {
      if (state.loading === "pending") {
        state.loading = "idle";
      }
      state.authError = null;
    },
    processFailed: (state, action) => {
      if (state.loading === "pending") {
        // Receive error msg from action.payload and put on a state property called errorMessage
        state.loading = "idle";
      }
      state.authError = "Error: " + action.payload;
    },
  },
  extraReducers: {},
});

export const signIn = (credentials, { firebase, firestore }) => async (
  dispatch,
  getState,
  getFirebase,
  getFirestore
) => {
  const firebaseRRF = getFirebase(); // NOT WORKING
  try {
    dispatch(processStarted());
    await firebase.login(credentials); // RRF'S Ehanced function
    // await firebase
    //   .auth()
    //   .signInWithEmailAndPassword(credentials.email, credentials.password);
    // await firebase.authWithPassword(credentials);
    dispatch(processCompleted());
  } catch (error) {
    const errorMsg = error.message;
    const [methodError, shortMsg] = errorMsg.split(":");
    dispatch(processFailed(shortMsg));
  }
};

export const signUp = (credentials, profile, { firebase, firestore }) => async (
  dispatch,
  getState,
  getFirebase,
  getFirestore
) => {
  const firebaseRRF = getFirebase(); // NOT WORKING
  try {
    dispatch(processStarted());
    // await firebase
    //   .auth()
    //   .createUserWithEmailAndPassword(credentials.email, credentials.password);
    // dispatch(processCompleted());

    await firebase.createUser(credentials, profile);
    dispatch(processCompleted());
  } catch (error) {
    const errorMsg = error.message;
    const errorMsgShort = errorMsg.split(":");
    dispatch(processFailed(errorMsgShort));
  }
};

//TODO: Unable to access getFirebase and thus cannot connect to firebase. FIX IT !

export const {
  processFailed,
  processCompleted,
  processStarted,
} = authSlice.actions;
export default authSlice.reducer;

My Ui component; SignIn.js

// FB instances
  const firebase = useFirebase(); // - Currently doing this
  const firestore = useFirestore(); // - Currently doing this
  const fbref = {
    firebase,
    firestore,
  };

  // Submit handler
  function handleSubmit(cred, fb) {
    setTimeout(() => {
      dispatch(login(cred, fb));
    }, 500);
  }
// I pass the firebase and firestore instances along with form data to the thunk action creator; login(). I don't want to keep doing this, I want to access getFirebase and getFirestore directly from the props on login() in my authSlice.js file ( where login is defined) 
                <Button
                  title="Login"
                  onPress={() => handleSubmit({ email, password }, fbref)}
                  backgroundColor={"#303030"}
                  width={dWidth("60%")}
                  height={"60px"}
                  borderRadius={"60px"}
                  textColor={"#fff"}
                  fontWeight={"bold"}
                  fontSize={"18px"}
                  textCase={"uppercase"}
                  customStyle={btnShadow}
                  buttonPaddingTop={"16px"}
                  buttonPaddingBottom={"16px"}
                  buttonMarginTop={"50px"}
                  buttonMarginBottom={"100px"}
                />

@oother332
Copy link

@Jsh007 Try thunkAPI.extra.getFirebase().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants