ReactFire

repository·main·Indexed 25 days ago

https://github.com/firebaseextended/reactfire

A Firebase library for React providing Hooks, Context Providers, and Components to simplify interaction with Firebase in web applications. It features real-time hooks for Auth and Firestore, safe library initialization, and support for React Concurrent Mode and Suspense. Key utilities include FirebaseAppProvider, useFirestoreDocData, and specialized hooks for Analytics, App Check, and Realtime Database.

Tokens
20.3K
Snippets
27
Records
154
Agent score
85%

What's inside reactfire

  1. Use ReactFire for real-time Firebase updates

    main

    ReactFire provides hooks to subscribe to Firebase SDK events (like Auth state or Firestore data) that automatically handle unsubscription when components unmount.

    Key features include:

    • Real-time hooks: Use hooks like useUser or useFirestoreCollection for automatic subscriptions.
    • Library access: Access Firebase SDK instances directly within components using hooks like useFirestore or useRemoteConfig.
    • Safe initialization: Use useInitFirestore or useInitRemoteConfig to ensure library settings (like enablePersistence) are applied before data fetching begins.
  2. Configure FirebaseAppProvider in index.js

    main

    To use ReactFire, you must wrap your application in the FirebaseAppProvider component and pass your Firebase configuration object to it. This is typically done in your entry point file (e.g., src/index.js).

    import { FirebaseAppProvider } from 'reactfire';
    
    const firebaseConfig = {
      /* Paste your config object from Firebase console here
      */
    };
    
    ReactDOM.render(
      <FirebaseAppProvider firebaseConfig={firebaseConfig}>
        <App />
      </FirebaseAppProvider>,
      document.getElementById('root')
    );
  3. Enable Concurrent Mode and Suspense support

    main

    ReactFire supports React's Concurrent Mode features, allowing loading states to be handled by <Suspense>. To enable this, set the suspense prop to true on the FirebaseAppProvider.

    Additionally, you can use <SuspenseWithPerf /> to automatically instrument Suspense load times with Firebase Performance Monitoring (RUM).

    <FirebaseAppProvider firebaseConfig={firebaseConfig} suspense={true}>
      <App />
    </FirebaseAppProvider>
  4. Enable Cloud Firestore offline persistence

    main

    To enable offline data persistence in Cloud Firestore, you must call enableIndexedDbPersistence before any other Firestore functions. Use the useInitFirestore hook to handle this initialization sequence and then pass the resulting instance to a FirestoreProvider.

    This ensures that all child components using Firestore hooks will work with a fully initialized instance that has persistence enabled.

    import { initializeFirestore, enableIndexedDbPersistence } from 'firebase/firestore';
    import { useInitFirestore, FirestoreProvider } from 'reactfire';
    
    function App() {
      const { status, data: firestoreInstance } = useInitFirestore(async (firebaseApp) => {
        const db = initializeFirestore(firebaseApp, {});
        await enableIndexedDbPersistence(db);
        return db;
      });
    
      if (status === 'loading') {
        return <LoadingSpinner />;
      }
    
      return (
        <FirestoreProvider sdk={firestoreInstance}>
          <CommentText commentId={commentId} />
          <LikeCount commentId={commentId} />
        </FirestoreProvider>
      );
    }
  5. Connect to the Firebase Local Emulator Suite

    main

    To use Firebase emulators, initialize your Firebase app and connect the emulators to the SDK instances before passing them to ReactFire providers.

    Important: To make this work, you must pass the initialized app instance to FirebaseAppProvider using the firebaseApp prop instead of using the firebaseConfig shortcut. This allows you to own the app instance at the module level.

    import { initializeApp } from 'firebase/app';
    import { getAuth, connectAuthEmulator } from 'firebase/auth';
    import { getFirestore, connectFirestoreEmulator } from 'firebase/firestore';
    
    import { FirebaseAppProvider, FirestoreProvider, AuthProvider } from 'reactfire';
    
    const app = initializeApp(firebaseConfig);
    const auth = getAuth(app);
    const firestore = getFirestore(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') {
      connectAuthEmulator(auth, 'http://localhost:9099');
      connectFirestoreEmulator(firestore, 'localhost', 8080);
    }
    
    function App() {
      return (
        <FirebaseAppProvider firebaseApp={app}>
          <AuthProvider sdk={auth}>
            <FirestoreProvider sdk={firestore}>
              <MyCoolApp />
            </FirestoreProvider>
          </AuthProvider>
        </FirebaseAppProvider>
      );
    }
  6. Initialize and use Remote Config

    main

    Use useInitRemoteConfig to handle the asynchronous initialization, fetching, and activation of Remote Config. Once initialized, pass the instance to RemoteConfigProvider. You can then use hooks like useRemoteConfigString(key) to retrieve specific configuration values.

    import { getRemoteConfig, fetchAndActivate } from 'firebase/remote-config';
    import { useInitRemoteConfig, RemoteConfigProvider } from 'reactfire';
    
    function App() {
      const { status, data: remoteConfigInstance } = useInitRemoteConfig(async (firebaseApp) => {
        const remoteConfig = getRemoteConfig(firebaseApp);
        remoteConfig.settings = {
          minimumFetchIntervalMillis: 10000,
          fetchTimeoutMillis: 10000,
        };
    
        await fetchAndActivate(remoteConfig);
        return remoteConfig;
      });
    
      if (status === 'loading') {
        return <span >initializing Remote Config...</span>;
      }
    
      return (
        <RemoteConfigProvider sdk={remoteConfigInstance}>
          <WelcomeMessage />
        </RemoteConfigProvider>
      );
    }
    
    function WelcomeMessage() {
      const { status, data: messageValue } = useRemoteConfigString('welcome-experiment');
      // ...
    }
  7. Install ReactFire and Firebase

    main

    To use ReactFire, you must install both reactfire and the firebase Web SDK. Depending on your target environment, you may also need to install polyfills for globalThis and Proxy.

    # npm
    npm install --save firebase reactfire
    
    # or
    
    yarn add firebase reactfire
  8. Set up ReactFire with FirebaseAppProvider

    main

    ReactFire uses React's Context API. To use ReactFire hooks, you must wrap your application (or a parent component) in a FirebaseAppProvider. You can provide your configuration via the firebaseConfig prop. Any child component can then access the initialized app using the useFirebaseApp() hook.

    // ** INDEX.JS **
    const firebaseConfig = {
      /* add your config object from the Firebase console */
    };
    
    render(
      <FirebaseAppProvider firebaseConfig={firebaseConfig}>
        <MyComponent />
      </FirebaseAppProvider>
    );
    
    // ** MyComponent.JS **
    
    function MyComponent(props) {
      // useFirestore will get the firebase app from Context!
      const app = useFirebaseApp();
    }
  9. Upgrade from ReactFire v3 to v4

    main

    Upgrading from ReactFire v3 to v4 involves breaking changes. Follow these steps to migrate:

    1. Update Dependencies: Install the latest versions of both firebase and reactfire.
    2. Initialize Product SDKs: You must now explicitly initialize each Firebase product and pass the initialized SDK into a provider component (e.g., using AuthProvider for Authentication). This replaces the previous implicit initialization.
    3. Replace Preload Functions: For asynchronous initialization tasks (such as accessing Firestore offline or activating Remote Config), use the new initialization hooks like useInitFirestore or useInitRemoteConfig instead of the old preload functions.
    4. Refactor to Modular Firebase SDK: Ensure your Firebase code is refactored to use the modular style required by the new Firebase SDK.
    # Update to the latest versions
    npm i firebase@latest reactfire@latest
    
    # or
    
    yarn add firebase@latest reactfire@latest
  10. Set up App Check with ReactFire

    main

    To protect your backend resources, initialize App Check using the Firebase SDK and then wrap your application in the AppCheckProvider from reactfire. The AppCheckProvider should be placed high in the component tree, before any other App-Check-compatible Firebase services.

    import { initializeAppCheck, ReCaptchaV3Provider } from 'firebase/app-check';
    import { useFirebaseApp, AppCheckProvider } from 'reactfire';
    
    // Create your reCAPTCHA v3 site key in the
    // "Project Settings > App Check" section of the Firebase console
    const APP_CHECK_TOKEN = 'abcdefghijklmnopqrstuvwxy-1234567890abcd';
    
    function FirebaseComponents({ children }) {
      const app = useFirebaseApp(); // a parent component contains a `FirebaseAppProvider`
    
      const appCheck = initializeAppCheck(app, {
        provider: new ReCaptchaV3Provider(APP_CHECK_TOKEN),
        isTokenAutoRefreshEnabled: true,
      });
    
      // Activate App Check at the top level before any component talks to an App-Check-compatible Firebase service
      return (
        <AppCheckProvider sdk={appCheck}>
          <DatabaseProvider sdk={database}>
            <MyCoolApp />
          </DatabaseProvider>
        </AppCheckProvider>
      );
    }
  11. Set up FirestoreProvider for Firestore access

    main

    To access Firestore services within your component tree, wrap your components in a FirestoreProvider. You can obtain the Firestore instance by passing the result of getFirestore(useFirebaseApp()) to the sdk prop.

    import { getFirestore } from 'firebase/firestore';
    import { FirestoreProvider, useFirebaseApp } from 'reactfire';
    
    function App() {
      const firestoreInstance = getFirestore(useFirebaseApp());
      return (
        <FirestoreProvider sdk={firestoreInstance}>
          {/* Your components here */}
        </FirestoreProvider>
      );
    }