4

am doing a project in react-redux (w hooks) with redux-thunk. Got to the point, where I wanted to use some kind of account authentication. I have chosen to use Firebase since it is popular. So I started to follow ninjas outdated course on yt. Knowing that, I was checking the documenation of firebase, on how to get authenticated using redux-thunk. Now I got to the point, that when I try to login into my firebase, I get the following error: "Firebase instance does not yet exist. Check your compose function."

A similar problem was described here, but this would be to easy (of course...): SO LINK

I can only assume, that the problem is somewhere in my store.js, in the compose function. Just, that I did everything by the book (or at least I think so):http://docs.react-redux-firebase.com/history/v3.0.0/docs/getting_started.html and nothing seems to help.

Maybe someone with a fresh look could check my code and tell me, where I have done a mistake.

Since I asume, that the error is in the store.js, I will start with it:


store.js:

import { createStore, applyMiddleware} from 'redux';
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from 'redux-thunk';

import { getFirebase } from 'react-redux-firebase';
// import { getFirestore, reduxFirestore } from "redux-firestore";

import rootReducer from './reducers/rootReducer';

const middlewares = [
    thunk.withExtraArgument({getFirebase})
  ];

const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));

export default store;

fbConfig.js

const fbConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
  };

export default fbConfig;

I Import the above mentioned files into my index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from "react-router-dom";

import store from './store';
import App from './components/App/App';

import firebase from "firebase/app";
import "firebase/auth"

import fbConfig from "./config/fbConfig";

// import { createFirestoreInstance } from "redux-firestore";
import { ReactReduxFirebaseProvider } from 'react-redux-firebase';

import registerServiceWorker from "./registerServiceWorker";

console.log(fbConfig);
firebase.initializeApp(fbConfig);

//rrf stores authenticated users' data in Cloud Firestore
const rrfConfig = {
  userProfile: "users",
  // useFirestoreForProfile: true,
}

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

ReactDOM.render(
  <BrowserRouter>
    <Provider store={store} >
      <ReactReduxFirebaseProvider {...rrfProps} >
        <App />
      </ReactReduxFirebaseProvider>
    </Provider>
  </BrowserRouter>,
  document.querySelector("#root")
);

registerServiceWorker();

rootReducer.js Here I also have a question, because as I was checking on the internet, a lot of people had only one file, that was handling the authentication requests (sign in, sign Out or sign up) called auth (ot at least in the root reducer, like auth: authReducer). I have splitted my logic into 3 separate files. Now I wonder, if I can do this, or should I also have an auth reducer?

import { combineReducers } from 'redux';
import { firebaseReducer } from "react-redux-firebase";

import SigninReducer from "./auth/signinReducer";
import SignoutReducer from "./auth/signoutReducer";
import SignupReducer from "./auth/signupReducer";

const rootReducer = combineReducers({
    firebase: firebaseReducer,

    signin: SigninReducer,
    signout: SignoutReducer,
    signup: SignupReducer
});

export default rootReducer;

signinReducer.js

import { GET_SIGNIN_SUCCESS, GET_SIGNIN_ERROR } from "../../actions/index";

const DefaultState = {
    authMsg: ""
};

const SigninReducer = (state = DefaultState, action) => {
    switch (action.type) {
        case GET_SIGNIN_ERROR:
            console.log("login failed");
            return {
                ...state,
                authMsg: "Unable to login"
            };
        case GET_SIGNIN_SUCCESS:
            console.log("login success");
            return {
                ...state,
                authMsg: "login success"
            };
    default:
        return state
    }
}

export default SigninReducer;

action/getSignin.js

import { GET_SIGNIN_ERROR, GET_SIGNIN_SUCCESS } from "../index";

export const getSignin = (credentials) => async (dispatch, getState, {getFirebase}) => {
    console.log(credentials);
    const firebase = getFirebase();
    console.log(firebase);
    try {
        await firebase()
            .auth()
            .signInWithEmailAndPassword(credentials.email, credentials.password)
            .then(() => {
                dispatch({
                    type: GET_SIGNIN_SUCCESS
                });
            })
            .catch((error) => {
                dispatch({
                    type: GET_SIGNIN_ERROR,
                    error
                });
            });
        
    } catch(e) {
        dispatch ({
            type: GET_SIGNIN_ERROR,
            payload: "Invalid login credentials."
        });
    }
};

component/userSignin.js

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import { getSignin } from "../../actions/auth/getSignin";

const UserSign = () => {
    const dispatch = useDispatch();

    const [ userStatus, setUserStatus ] = useState ({
        email: "",
        password: ""
    })

    const handleSubmit = (event) => {
        dispatch(getSignin(userStatus));
        event.preventDefault();
    }

    const handleChange = (event) => {
        const { id, value } = event.target;
        setUserStatus({
                ...userStatus,
                [id]: value
        })
    }

    const showLogin = () => {
        return (
            <div>
                <h4>Login</h4>
                <form onSubmit={handleSubmit}>
                    <div>
                        <label htmlFor="email">Email address</label>
                        <input type="email" id="email" onChange={handleChange} required />
                    </div>
                    <div>
                        <label htmlFor="password">Your Password</label>
                        <input type="password" id="password" onChange={handleChange} required />
                    </div>
                    <button>Login</button>
                </form>
            </div>
        )
    }

    return (
        <div>
            {showLogin()}
            <Link to={"/signup"}><p>SignUp</p></Link>
            <Link to={"/"}>Back</Link>
        </div>
    )
}

export default UserSign;

When I check the console.log(fbConfig), then I see, that firebase config i initialized (API_KEY, etc). Also in my action/getSignin.js file I can console.log my login and password and check, that they are passed in there. But I get an error, because my API_KEY is missing.

I double checked the API_KEY value with the one given by Firebase and they do match.

I am out of ideas. Please help

Aaron Erdwyn
  • 129
  • 13
  • My best guess without having tested it is that you need to instantiate a Firebase instance and pass it to `createStore()`. How is there supposed to be an instance if you don't create one? – dmuensterer Oct 18 '20 at 20:29
  • Hmm, I initialize it in my index.js: `firebase.initializeApp(fbConfig);` or am I wrong? – Aaron Erdwyn Oct 18 '20 at 20:46
  • Also in the documentation: http://docs.react-redux-firebase.com/history/v3.0.0/docs/integrations/thunks.html I do not see any firebaseConfig beeing initalized :/. – Aaron Erdwyn Oct 18 '20 at 20:59

1 Answers1

1

So I got the issue.

I got my API_KEY values etc stored in my .env.local file. Turns out, that if I write them directly in the fbConfig file, then everything works. Wonder why, because in my previous app I did exacly the same thing and it worked. Also I could console.log out the values from the .env.local file in my index.js. But somehow they did not got initialized.

Well, now everything is working fine.

Aaron Erdwyn
  • 129
  • 13