Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 31 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,59 @@
# Reactfire
# ReactFire

Hooks, Context Providers, and Components that make it easy to interact with
Firebase.

> If you're looking for docs for the _deprecated_ ReactFire v1 (the one that
> uses mixins), click
> [here](https://github.com/FirebaseExtended/reactfire/tree/v1.0.0)

**Status: Alpha**. ReactFire is meant for React Concurrent Mode, which is only
⚠️ **Status: Experimental**. The API is intended to be stable, but ReactFire is meant for React Concurrent Mode, which is only
available in
[experimental React builds](https://reactjs.org/docs/concurrent-mode-adoption.html#installation).

## What is ReactFire?

- **Easy realtime updates for your function components** - Reactfire's hooks,
like `useFirestoreCollection` and `useUser`, let you easily subscribe to
events, and automatically unsubscribe when your component unmounts.
- **Loading states handled by `<Suspense>`** - Reactfire's hooks throw promises
- **Easy realtime updates for your function components** - Hooks
like `useUser`and `useFirestoreCollection` let you easily subscribe to
auth state, realtime data, and all other Firebase SDK events. Plus, they automatically unsubscribe when your component unmounts.
- **Loading states handled by `<Suspense>`** - ReactFire's hooks throw promises
that Suspense can catch. No more `isLoaded ?...` - let React
[handle it for you](https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-166-shipped-the-one-with-suspense-for-code-splitting).
- **Dead-simple Real User Monitoring (RUM)** - Easily enable Firebase
Performance Monitoring's
[automatic traces](https://firebase.google.com/docs/perf-mon/automatic-web),
and instrument your Suspenseful loads with Reactfire's `<SuspenseWithPerf>`
component
[handle it for you](https://reactjs.org/docs/concurrent-mode-suspense.html).
- **Faster initial page load times** - Load only the code you need, when you need it, with `useFirestore`, `useAuth`, `useRemoteConfig`, and more.
- **Convenient components for common use cases** - Only want to render a component if a user is signed in? Wrap it in `<AuthCheck />`. Need to automatically instrument your `Suspense` load times with [RUM](https://firebase.google.com/docs/perf-mon)? Use `<SuspenseWithPef />`.

## Install

```bash
# npm
npm install --save reactfire
npm install --save reactfire firebase

# yarn
yarn add reactfire
yarn add reactfire firebase
```

- [**Quickstart**](./docs/quickstart.md)
- [**Common Use Cases**](./docs/use.md)
- [**API Reference**](./docs/reference.md)

## Example use

Check out the
[live version on StackBlitz](https://stackblitz.com/edit/reactfire-sample)!
[live version on StackBlitz](https://stackblitz.com/fork/reactfire-sample)!

```jsx
import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';
import { createRoot } from 'react-dom';
import {
FirebaseAppProvider,
useFirestoreDocData,
useFirestore,
SuspenseWithPerf
} from 'reactfire';

const firebaseConfig = {
/* add your config object from the Firebase console */
/* Add your config from the Firebase Console */
};

function Burrito() {
// lazy load the Firestore SDK and create a ref
// lazy load the Firestore SDK
// and create a ref
const burritoRef = useFirestore()
.collection('tryreactfire')
.doc('burrito');
Expand All @@ -65,18 +63,15 @@ function Burrito() {
// and then streams live updates
const burrito = useFirestoreDocData(burritoRef);

// get the value from the doc
const isYummy = burrito.yummy;

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

function App() {
return (
<FirebaseAppProvider firebaseConfig={firebaseConfig} initPerformance>
<FirebaseAppProvider firebaseConfig={firebaseConfig}>
<h1>🌯</h1>
<SuspenseWithPerf
fallback={'loading burrito status...'}
fallback={<p>loading burrito status...</p>}
traceId={'load-burrito-status'}
>
<Burrito />
Expand All @@ -85,30 +80,13 @@ function App() {
);
}

render(<App />, document.getElementById('root'));
// Enable Concurrent Mode
// https://reactjs.org/docs/concurrent-mode-adoption.html#enabling-concurrent-mode
createRoot(document.getElementById('root')).render(<App />);
```

## Learn More

- [**Quickstart**](./docs/quickstart.md)
- [**Common Use Cases**](./docs/use.md)
- [**API Reference**](./docs/reference.md)

## Contributing

### For development
---

1. [Clone](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository)
this repository (or a
[fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo#propose-changes-to-someone-elses-project))
1. At the project root, install all modules by running `yarn install`.
1. `cd` into the _reactfire_ directory. Run `yarn` and `yarn watch`.
1. In a new terminal, `cd` into the _reactfire/sample_ directory. run `yarn` and
`yarn start`.
1. Head over to https://localhost:3000 to see the running sample! If you edit
the reactfire source, the sample will reload.

### Testing

1. `cd` into the _reactfire/reactfire_ directory
1. run `yarn test`
> If you're looking for docs for the _deprecated_ ReactFire v1 (the one that
> uses mixins), click
> [here](https://github.com/FirebaseExtended/reactfire/tree/v1.0.0)
36 changes: 18 additions & 18 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Reactfire Quickstart
# ReactFire Quickstart

⚛ + 🔥 = 🌯

We'll build a web app that displays, in _real time_, the tastiness of a burrito. It will listen to **Cloud Firestore** for its data, and we'll configure **Firebase Performance Monitoring** so we can get some perf stats.

To see the completed app, check out [this StackBlitz workspace](https://stackblitz.com/edit/reactfire-sample).
To see the completed app, check out [this StackBlitz workspace](https://stackblitz.com/fork/reactfire-sample).

## 1. In a terminal, create a fresh React app and `cd` into its directory.
## 1. In a terminal, create a fresh React app and `cd` into its directory

> Prerequisite: make sure you have [Node.js](https://nodejs.org/en/) installed.

Expand All @@ -15,7 +15,7 @@ npx create-react-app myapp
cd myapp
```

## 2. Install reactfire and the Firebase SDK
## 2. Install ReactFire and the Firebase SDK

```bash
# yarn
Expand Down Expand Up @@ -48,12 +48,11 @@ npm install --save firebase reactfire

## 4. Modify `src/index.js`

1. Import firebase and reactfire
1. Import Firebase and ReactFire

```js
//...
import { FirebaseAppProvider } from 'reactfire';
import 'firebase/performance';
//...
```

Expand All @@ -64,11 +63,10 @@ npm install --save firebase reactfire
const firebaseConfig = {
/* add your config object from Firebase console */
};
ReactDOM.render(
<FirebaseAppProvider firebaseConfig={firebaseConfig} initPerformance>
ReactDOM.createRoot(document.getElementById('root')).render(
<FirebaseAppProvider firebaseConfig={firebaseConfig}>
<App />
</FirebaseAppProvider>,
document.getElementById('root')
</FirebaseAppProvider>
);
//...
```
Expand All @@ -88,11 +86,8 @@ npm install --save firebase reactfire
```jsx
//...
function Burrito() {
// lazy load the Firestore SDK
const firestore = useFirestore();

// create a document reference
const burritoRef = firestore()
// lazy load the Firestore SDK and create a document reference
const burritoRef = useFirestore()
.collection('tryreactfire')
.doc('burrito');

Expand All @@ -118,6 +113,11 @@ Replace the `App` function with the following:
function App() {
return (
<div className="App">
{/*
SuspenseWithPerf behaves the same as Suspense,
but also automatically measures load times with the User Timing API
and reports it to Firebase Performance Monitoring
*/}
<SuspenseWithPerf
fallback={'loading burrito status...'}
traceId={'load-burrito-status'}
Expand All @@ -140,11 +140,11 @@ npm run start

1. Edit the value of `yummy` in the Firebase console, and watch it update in real time in your app! 🔥🔥🔥

## _But what about Firebase Performance Monitoring?_
## _About Firebase Performance Monitoring_

By passing the `initPerformance` prop to `FirebaseAppProvider`, our app will automatically measure [common performance stats](https://firebase.google.com/docs/perf-mon/automatic-web), as well as report on our custom trace, `load-burrito-status`, that we set in the `traceId` prop of `SuspenseWithPerf`.
`SuspenseWithPerf` will lazy load the Firebase Performance Monitoring library and report on on our custom trace, `load-burrito-status`, that we set in the `traceId` prop of `SuspenseWithPerf`. In addition, it will automatically measure [common performance stats](https://firebase.google.com/docs/perf-mon/automatic-web)!

However, Firebase Performance Monitoring can take about 12 hours to crunch your data and show it in the _Performance_ tab of the Firebase console.
Note that Firebase Performance Monitoring can take about 12 hours to crunch your data and show it in the _Performance_ tab of the Firebase console.

This is an example of some of the stats in the Firebase Performance Monitoring console after 12 hours:

Expand Down
37 changes: 37 additions & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- Cloud Storage
- [`useStorageTask`](#useStorageTask)
- [`useStorageDownloadURL`](#useStorageDownloadURL)
- [`useObservable`](#useobservablet)
- [ReactFireOptions](#ReactFireOptions)

- [Components](#Components)
Expand All @@ -56,6 +57,8 @@
- [`preloadPerformance`](#preloadPerformance)
- [`preloadRemoteConfig`](#preloadRemoteConfig)
- [`preloadStorage`](#preloadStorage)
- Data
- [`preloadFirestoreDoc`](#preloadFirestoreDoc)

## Hooks

Expand Down Expand Up @@ -368,6 +371,8 @@ _Throws a Promise by default_

Subscribe to a storage blob's download URL

useobservable link

_Throws a Promise by default_

### Parameters
Expand All @@ -381,6 +386,21 @@ _Throws a Promise by default_

`string`

### `useObservable<T>`

_Throws a Promise by default_

| Parameter | Type | Description |
| ------------------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| source | `Observable` | The observable whose values you want to subscribe to |
| observableId | `string` | A unique id. If this id matches an observable already in the cache, `useObservable` will reuse that observable instead of the one passed in. |
| startWithValue _?_ | `T` | A value to emit first (if you don't want `useObservable` to throw a Promise) |
| deps | React.DependencyList | A list of values that, when changed, should cause `useObservable` to re-subscribe to its observable |

##### Returns

`T`

## ReactFireOptions

| Property | Type |
Expand Down Expand Up @@ -578,3 +598,20 @@ Start importing the `firebase/storage` package.
#### Returns

`Promise<`[`firebase.storage`](https://firebase.google.com/docs/reference/js/firebase.storage)`>`

### `preloadFirestoreDoc`

⚠️ experimental

Starts subscribing to a Firestore document in the background. Cleans itself up after 30 seconds if `useFirestoreDoc` calls are made.

#### Parameters

| Parameter | Type | Description |
| ----------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| refProvider | `(firestore: firebase.firestore.Firestore) => firestore.DocumentReference` | A function that is called when the firestore SDK is ready and generates a DocumentReference to read |
| firebaseApp | `firebase.app.App` | The firebase app |

#### Returns

`Promise<Obsevable<any>>`
Loading