Marian Rick
Marian Rick

Reputation: 3440

How to use firestore emulator with reactfire?

I have set up firestore locally following the firebase docs and I can test firebase functions easily. I would love to develop locally with an local firestore database. In the docs they provide the following code:

// Initialize your Web app as described in the Get started for Web
// Firebase previously initialized using firebase.initializeApp().
var db = firebase.firestore();
if (location.hostname === "localhost") {
  db.settings({
    host: "localhost:8080",
    ssl: false
  });
}

How can I do this, if I use reactfire with reactjs to init firebase? Currently its initialised like this:

const firebaseConfig = {
  apiKey: "",
  authDomain: "example.firebaseapp.com",
  databaseURL: "https://example.firebaseio.com",
  projectId: "example",
  storageBucket: "example.appspot.com",
  messagingSenderId: "",
  appId: "",
  measurementId: ""
};

ReactDOM.render(
  <React.StrictMode>
    <FirebaseAppProvider firebaseConfig={firebaseConfig}>
      <App/>
    </FirebaseAppProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

Should I just manipulate the databaseURL: in the config or is there another best practice to connect to the local emulator firestore?

Upvotes: 4

Views: 1746

Answers (3)

DevGoldm
DevGoldm

Reputation: 828

The Reactfire docs on emulation now differ from what was mentioned in the earlier answers, they were updated August 2021.

I've modified their example to show you how to use the firestore and auth emulators with Firebase v9+:

import { getAuth, connectAuthEmulator } from 'firebase/auth'; // Firebase v9+
import { getFirestore, connectFirestoreEmulator } from 'firebase/firestore'; // Firebase v9+

import { FirebaseAppProvider, DatabaseProvider, AuthProvider, useFirebaseApp } from 'reactfire';

function FirebaseComponents({ children }) {
  const app = useFirebaseApp();
  const firestore = getFirestore(app);
  const auth = getAuth(app);

  // Check for dev/test mode however your app tracks that.
  // `process.env.NODE_ENV` is a common React pattern
  if (process.env.NODE_ENV !== 'production') {
    // Set up emulators
    connectFirestoreEmulator(firestore, 'localhost', 8080);
    connectAuthEmulator(auth, 'http://localhost:9099');
  }

  return (
    <AuthProvider sdk={auth}>
      <FirestoreProvider sdk={firestore}>
        <MyCoolAppThatUsesAuthAndFirestore />
      </FirestoreProvider>
    </AuthProvider>
  );
}

Similar connection patterns also exist for other emulators (connectStorageEmulator, connectDatabaseEmulator etc...)

Upvotes: 1

LeoSteinStein
LeoSteinStein

Reputation: 33

Thanks for your help guys! Reactfire api changed once again, this is currently working solution:


import React from 'react';
import logo from './logo.svg';
import './App.css';
import Answers from './components/answers'
import HomeScreen from './screens/HomeScreen'
import { preloadFirestore, useFirebaseApp } from 'reactfire'
import firebase from 'firebase'

const preloadSDKs = (firebaseApp: firebase.app.App) => {
  return Promise.all([
    preloadFirestore({
      firebaseApp,
      setup: firestore => {
      return firestore().settings({host: 'localhost:8080', ssl: false});
    }
    }),
    // preloadDatabase(),
    // preloadStorage(),
    // etc.
  ]);
};

function App() {
  const firebaseApp = useFirebaseApp();

  preloadSDKs(firebaseApp).then(() => Promise.resolve());

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <HomeScreen />
      </header>
    </div>
  );
}

export default App;

Upvotes: 1

Marian Rick
Marian Rick

Reputation: 3440

I have found an Github Issue in which its suggested to use preloadFirestore from reactfire.

They although provide an example in their sample app:

preloadFirestore(firebaseApp, firestore => { 
  return firestore().enablePersistence(); 
}), 

If you want to use it like they do, you have a basic setup like this:

// create a preload function to combine multiple preloads
const preloadSDKs = firebaseApp => {
  return Promise.all([
    preloadFirestore(firebaseApp, firestore => {
      return firestore().settings({host: 'localhost:8080', ssl: false});
    }),
    // preloadDatabase(), 
    // preloadStorage(), 
    // etc.
  ]);
};

function App() {
  const firebaseApp = useFirebaseApp();

  // Kick off fetches for SDKs and data that
  // we know our components will eventually need.
  //
  // This is OPTIONAL but encouraged as part of the render-as-you-fetch pattern
  // https://reactjs.org/docs/concurrent-mode-suspense.html#approach-3-render-as-you-fetch-using-suspense
  preloadSDKs(firebaseApp).then(() => Promise.resolve());

  return (
    <YourComponents />
  )
}

Afterwards you can just use useFirestore() anywhere in the app to lazy load it with the settings above.

Hints:

  • You have to use the <FirebaseAppProvider /> before preloading the SDKs
  • Your component preloading the SDKs has to be wrapped inside a <Suspense /> or <SuspenseWithPerf /> component
  • Check the reactfire demo app to see how you can not only preload SDKs but data as well

Upvotes: 0

Related Questions