0
votes

Getting around firebase authentication but it keeps on throwing the following TypeError message and breaks the app:

TypeError: getfirebase is not a function

Please take a look at my store and authReducer if I'm doing it wrong. In my store, I have provided reduxfirestore with getfirestore and also getfirebase to react-redux-firebase. I'm using v2 of react-redux-firebase.

** store.js

import rrfConfig from "../config/rrfConfig";
import { reduxFirestore, getFirestore } from "redux-firestore";
import { reactReduxFirebase, getFirebase } from "react-redux-firebase";
import { createStore, compose, applyMiddleware } from "redux";
import rootReducer from "./reducers/rootReducer";
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/auth";
import firebaseConfig from "../config/fbConfig";
import thunk from "redux-thunk";
firebase.initializeApp(firebaseConfig);
firebase.firestore();

const initialState = {};

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

export default store;

**authActions.js

export const signInAction = 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 });
      });
  };
};

**authReducer

const initialState = {
  authError: null
};

const authReducer = (state = initialState, action) => {
  switch (action.type) {
    case "LOGIN_ERROR":
      console.log("login error");
      return {
        ...state,
        authError: "login failed"
      };
    case "LOGIN_SUCCESS":
      console.log("login success");
      return {
        ...state,
        authError: null
      };
    default:
      return state;
  }
};

export default authReducer;

**rootReducer

import { combineReducers } from "redux";
import authReducer from "./authReducer";
import projectReducer from "./projectReducer";
import { firestoreReducer } from "redux-firestore";
import { firebaseReducer } from "react-redux-firebase";

const rootReducer = combineReducers({
  auth: authReducer,
  project: projectReducer,
  firestore: firestoreReducer,
  firebase: firebaseReducer
});

export default rootReducer;

package.json

{
  "name": "ghandhi-land",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "firebase": "^6.0.4",
    "materialize-css": "^1.0.0-rc.2",
    "node-sass": "^4.11.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-redux": "^5.1.1",
    "react-redux-firebase": "^2.2.4",
    "react-router-dom": "^5.0.0",
    "react-scripts": "3.0.1",
    "redux": "^4.0.1",
    "redux-firestore": "^0.8.0",
    "redux-thunk": "^2.3.0"
  }
}

**SignIn component

import { connect } from "react-redux";
import { signInAction } from "../../store/actions/authActions";
class SignIn extends Component {
  state = {
    email: "",
    password: " "
  };

  handleChange = e => {
    this.setState({
      [e.target.id]: e.target.value
    });
  };
  handleSubmit = e => {
    e.preventDefault();
    this.props.signIn(this.state);
  };

  render() {
    return (
      <div className="container">
        <form onSubmit={this.handleSubmit} className="white">
          <h5 className="grey-text text-darken-3">Sign In</h5>
          <div className="input-field">
            <label htmlFor="email">Email</label>
            <input type="email" id="email" onChange={this.handleChange} />
          </div>
          <div className="input-field">
            <label htmlFor="password">password</label>
            <input type="password" id="password" onChange={this.handleChange} />
          </div>
          <div className="input-field">
            <button className="btn pink lighten-1 z-depth-0">Login</button>
          </div>
        </form>
      </div>
    );
  }
}
const mapDispatchToProps = dispatch => {
  return {
    signIn: credentials => dispatch(signInAction(credentials))
  };
};

export default connect(
  null,
  mapDispatchToProps
)(SignIn);
1
Your code seems fine. Could you console.log the value of getFirebase in store.js? Also, where are you exactly getting the TypeError error? Is it when you are executing the signInAction method? - mgarcia
when i console.log getfirebase, this what it saying ƒ getFirebase() { if (!firebaseInstance) { throw new Error('Firebase instance does not yet exist. Check your compose function.'); } return firebaseInstance; } - yrufai
and yes it throws this typeError when executing the signInAction - yrufai
@mgarcia. why is the getfirebase undefined? - yrufai

1 Answers

1
votes

When you are composing the redux middlewares you are applying the thunk middleware with this statement:

applyMiddleware(thunk.withExtraArgument({ getFirebase, getFirestore }))

The names of the methods you are passing as an extra argument are in camelcase notation: getFirebase and getFirestore.

However, when you are trying to retrieve the extra argument in authActions.js you are destructuring it as getfirebase:

return (dispatch, getState, { getfirebase })

You should destructure your object with the same notation (in camelcase). So, your code should be:

return (dispatch, getState, { getFirebase })