If you haven't, install the firebase JS client.
yarn add firebase
# Or
npm i firebase
Install @react-firebase/database
yarn add @react-firebase/database # or npm i @react-firebase/database
Change PROJECT_NAME
to your project name and grab your firebase config here :
https://console.firebase.google.com/project/PROJECT_NAME/settings/general/
Your config file should look something like this :
// Firebase Config
const config = {
apiKey: "API_KEY",
projectId: "PROJECT_ID",
databaseURL: "DATABASE_URL",
authDomain: "AUTH_DOMAIN",
// OPTIONAL
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "MESSAGING_SENDER_ID"
};
Place a FirebaseDatabaseProvider
component at the top level of your app (anywhere as long as it's above the other Realtime Database components).
import { FirebaseDatabaseProvider } from "@react-firebase/database";
// Before
function App() {
return (
<div>
This is my app <SomeOtherComponent />
</div>
);
}
// After
function App() {
return (
<FirebaseDatabaseProvider>
<div>
This is my app
<SomeOtherComponent />
</div>
</FirebaseDatabaseProvider>
);
}
If you need to authenticate to access your data, check out @react-firebase/auth
Check API for a list of supported props.
class App extends React.Component<any, AppState> {
state = {
limit: 2
};
render() {
return (
<div style={styles}>
<FirebaseDatabaseProvider firebase={firebase} {...config}>
<div>
<FirebaseDatabaseNode
path="user_bookmarks/"
limitToFirst={this.state.limit}
// orderByKey
orderByValue={"created_on"}
>
{d => {
return (
<React.Fragment>
<pre>Path {d.path}</pre>
<pre style={{ height: 300, overflow: "auto" }}>
Value {s(d.value)}
</pre>
<button
onClick={() => {
this.setState(state => ({ limit: state.limit + 2 }));
}}
>
Load more
</button>
</React.Fragment>
);
}}
</FirebaseDatabaseNode>
</div>
</FirebaseDatabaseProvider>
</div>
);
}
}
The FirebaseDatabaseMutation
allows you to render components that run Firebase mutations (update, set, push).
A setMutation
function that returns a promise is provided to the children function.
FirebaseDatabaseMutation needs 3 props :
string
"update" | "set" | "push"
children:
| ( { runMutation: (value:any) => Promise<{key?:string}> } ) => ReactNode | | :---------------------------------------------------------------------- |
class MutationExample extends React.Component {
state = {
pushedKey: ""
};
render() {
const { state } = this;
return (
<React.Fragment>
<FirebaseDatabaseMutation type="push" path={path}>
{({ runMutation }) => {
return (
<div>
<button
data-testid="test-push"
onClick={async () => {
const { key } = await runMutation({ TEST: "DATA" });
this.setState({ pushedKey: key });
}}
>
Push
</button>
</div>
);
}}
</FirebaseDatabaseMutation>
{state.pushedKey !== "" && (
<div>
<div data-testid="test-push-result">{state.pushedKey}</div>
<div>
<FirebaseDatabaseNode path={`${path}/${state.pushedKey}`}>
{({ value }) => <pre>{s(value)}</pre>}
</FirebaseDatabaseNode>
<FirebaseDatabaseMutation
type="set"
path={`${path}/${state.pushedKey}`}
>
{({ runMutation }) => (
<button
onClick={async () => {
runMutation(null);
this.setState({ pushedKey: "" });
}}
>
Delete
</button>
)}
</FirebaseDatabaseMutation>
</div>
</div>
)}
</React.Fragment>
);
}
}
Suppose you have a shared counter that many can increment. To avoid race conditions, use transactions.
FirebaseDatabaseTransaction needs 2 props:
string
children:
| ( { runTransaction: ({ reducer: (value:any)=>any }) => Promise<{key?:string}> } ) => ReactNode | | :--------------------------------------------------------------------------------------------- |