prescottprue / react-redux-firebase

Redux bindings for Firebase. Includes React Hooks and Higher Order Components.
https://react-redux-firebase.com
MIT License
2.55k stars 556 forks source link

firebase.updateProfile throws error when using firestore to store profile #932

Open chrislewispac opened 4 years ago

chrislewispac commented 4 years ago

I have used the example from the docs...

import React from "react";
import { useSelector } from "react-redux";
import { useFirebase } from "react-redux-firebase";

export default function Title(props) {
  const firebase = useFirebase();
  const profile = useSelector((state) => state.firebase.profile);

  console.log(profile);

  function updateUserProfile() {
    return firebase.updateProfile({ role: "admin" });
  }

  return (
    <React.Fragment>
      <h2>Update User Profile</h2>
      <button onClick={updateUserProfile}>Add Role To User</button>
    </React.Fragment>
  );
}

When I use the following configs:

const rrfConfig = {
  userProfile: "users",
  useFirestoreForProfile: true, // Firestore for Profile instead of Realtime DB/
  enableClaims: true, // Get custom claims along with the profile
  presence: "presence", // where list of online users is stored in database
  sessions: "sessions", // where list of user sessions is stored in database (presence must be enabled)
};

I get the following error:


firebaseNamespaceCore.ts:227 Uncaught TypeError: Cannot read property '_getService' of undefined

-----------------

 224 | // option added to the no-explicit-any rule when ESlint releases it.
  225 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
  226 | function(...args: any) {
> 227 |   const serviceFxn = this._getService.bind(this, componentName);
      | ^  228 |   return serviceFxn.apply(
  229 |     this,
  230 |     component.multipleInstances ? args : []

If I use the following configs:

// react-redux-firebase config
const rrfConfig = {
  userProfile: "users",
  enableClaims: true, // Get custom claims along with the profile
  presence: "presence", // where list of online users is stored in database
  sessions: "sessions", // where list of user sessions is stored in database (presence must be enabled)
};

It performs as expected.

prescottprue commented 4 years ago

It looks like it is having an issue finding Firestore, how does your Firebase import look? Does it include importing of Firestore?

chrislewispac commented 4 years ago

I am using firestore successfully for all other purposes. I am not importing firestore in the actual component where I am attempting to update the profile, I am only importing it here. (and in other components where I am using it to make queries/updates/etc.

//index,js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createMemoryHistory } from "history";
import routes from "./routes";
import configureStore from "./store";
import { myFirebase } from "./firebase";
import { ReactReduxFirebaseProvider } from "react-redux-firebase";
import { createFirestoreInstance } from "redux-firestore";
import * as serviceWorker from "./serviceWorker";

const syncHistoryWithStore = (store, history) => {
  const { router } = store.getState();
  if (router && router.location) {
    history.replace(router.location);
  }
};

const initialState = {};
const routerHistory = createMemoryHistory();
const store = configureStore(initialState, routerHistory);
syncHistoryWithStore(store, routerHistory);

myFirebase.firestore(); // <- needed if using firestore

// react-redux-firebase config
const rrfConfig = {
  userProfile: "users",
  // useFirestoreForProfile: true, // Firestore for Profile instead of Realtime DB/
  enableClaims: true, // Get custom claims along with the profile
  presence: "presence", // where list of online users is stored in database
  sessions: "sessions", // where list of user sessions is stored in database (presence must be enabled)
};

const rrfProps = {
  firebase: myFirebase,
  config: rrfConfig,
  dispatch: store.dispatch,
  createFirestoreInstance, // <- needed if using firestore
};

ReactDOM.render(
  <Provider store={store}>
    <ReactReduxFirebaseProvider {...rrfProps}>
      {routes}
    </ReactReduxFirebaseProvider>
  </Provider>,
  document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
prescottprue commented 4 years ago

@chrislewispac Can you post what you have in the file in this import: import { myFirebase } from "./firebase"; - it seems that is where Firebase is being imported

I'm looking to try to replicate the issue

chrislewispac commented 4 years ago
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/database";
import "firebase/firestore";

//TODO: move to env file
const fbConfig = {
  apiKey: "DELETED",
  authDomain: "DELETED",
  databaseURL: "DELETED",
  projectId: "DELETED",
  storageBucket: "DELETED",
  messagingSenderId: "DELETED",
  appId: "DELETED",
};

// Initialize firebase instance
export const myFirebase = firebase.initializeApp(fbConfig);
prescottprue commented 3 years ago

@chrislewispac What version of the Firebase SDK are you using? According to the firebase docs there is a new import style for the newer version, but just trying to make sure I replicate correctly

The new import style is:

import firebase from "firebase/app";
import "firebase/auth";
import "firebase/database";
import "firebase/firestore";
chrislewispac commented 3 years ago

I was using the new import style with version "firebase": "^7.13.2",

vittau commented 3 years ago

I'm getting an error in the exact same line, with a very similar setup, except it's TypeError: this is undefined. My imports are as @prescottprue described. Versions are:

"firebase": "^8.6.1",
"react-redux-firebase": "^3.10.0",
"redux-firestore": "^0.15.0",

Did anyone else run into this?

EDIT: So, it turns out the problem is using the returned instance from initializeApp like @chrislewispac does here and then uses it in the rrfProps (here). Importing and using firebase directly (import firebase from 'firebase/app') fixed my problem.