Files
reactfire/docs/use.md
2019-08-05 11:29:48 -07:00

4.1 KiB

Common Patterns

Access your firebase object from any component

Since reactfire uses React's Context API, any component under a FirebaseAppProvider can use useFirebaseApp() to get your initialized app.

// ** INDEX.JS **
const firebaseConfig = {
  /* add your config object from the Firebase console */
};

render(
  <FirebaseAppProvider firebaseConfig={firebaseConfig}>
    <MyApp />
  </FirebaseAppProvider>
);

// ** MYCOMPONENT.JS **

function MyComponent(props) {
  const firebaseApp = useFirebaseApp();
  const documentReference = firebaseApp
    .firestore()
    .collection('burritos')
    .doc('vegetarian');

  // ...
}

Manage Loading States

Reactfire is designed to integrate with React's Suspense API, but also supports use cases where Suspense isn't needed or wanted.

Default: Suspense

Say we have a component called Burrito that uses useFirestoreDoc:

function Burrito() {
  const firebaseApp = useFirebaseApp();
  const burritoRef = firebaseApp
    .firestore()
    .collection('tryreactfire')
    .doc('burrito');

  // subscribe to the doc. just one line!
  // throws a Promise for Suspense to catch,
  // and then streams live updates
  const burritoDoc = useFirestoreDoc(burritoRef);

  const isYummy = burritoDoc.data().yummy;

  return <p>The burrito is {isYummy ? 'good' : 'bad'}!</p>;
}

The parent component of Burrito can use Suspense to render a fallback component until useFirestoreDoc returns a value:

function FoodRatings() {
  return (
    <Suspense fallback={'loading burrito status...'}>
      <Burrito />
    </Suspense>
  );
}

Bonus: SuspenseWithPerf

Reactfire provides an a wrapper around Suspense called SuspenseWithPerf that instruments your Suspense loads with a Firebase Performance Monitoring custom trace. It looks like this:

function FoodRatings() {
  return (
    <SuspenseWithPerf
      fallback={'loading burrito status...'}
      traceId={'load-burrito-status'}
    >
      <Burrito />
    </SuspenseWithPerf>
  );
}

Provide an initial value

What if we don't want to use Suspense, or we're server rendering and we know what the initial value should be? In that case we can provide an initial value to any Reactfire hook:

function Burrito() {
  const firebaseApp = useFirebaseApp();
  const burritoRef = firebaseApp
    .firestore()
    .collection('tryreactfire')
    .doc('burrito');

  // subscribe to the doc. just one line!
  // returns the `startWithValue`,
  // and then streams live updates
  const burritoDoc = useFirestoreDoc(burritoRef, {
    startWithValue: {
      data: () => {
        yummy: true;
      }
    }
  });

  const isYummy = burritoDoc.data().yummy;

  return <p>The burrito is {isYummy ? 'good' : 'bad'}!</p>;
}

The parent component of Burrito now doesn't need to use Suspense:

function FoodRatings() {
  return <Burrito />;
}

Access the current user

The useUser() hook returns the currently signed-in user. Like the other Reactfire Hooks, you need to wrap it in Suspense or provide a startWithValue.

function HomePage(props) {
  // no need to use useFirebaseApp - useUser calls it under the hood
  const user = useUser();

  return <h1>Welcome Back {user.displayName}!</h1>;
}

Decide what to render based on a user's auth state

The AuthCheck component makes it easy to hide/show UI elements based on a user's auth state. It will render its children if a user is signed in, but if they are not signed in, it renders its fallback prop:

render(
  <AuthCheck fallback={<LoginPage />}>
    <HomePage />
  </AuthCheck>
);