User to DB code example
Let's see the code for adding a user to your database after they sign in.
Now that you've read the high-level explanation of adding a user to the database, let's see some code.
If you want to skip up to the code, you can see the example on Github. You can also scroll down to "Add user exists in DB logic."
Make sure you've already completed the setup guide, installation & have deployed your app before continuing.
- 1.Add a
userExistsInDb
state variable. - 2.Add
onAuthStateChanged
prop toDoormanProvider
. This function gets called whenever the user signs in or out.- 1.Inside this function, call your DB to see if user exists already, and if not, send to the onboarding flow.
- 2.Call
setUserExistsInDb
to update the state based on the DB's response.
- 3.When
userExistsInDb
isfalse
, render anOnboarding
screen that lets users enter information, and then adds them to the database. This goes inside ofAuthGate
.- 1.Call
setUserExistsInDb(true)
when a user is successfully added to the DB from theOnboarding
screen to update the state.
We're going to create 3 files. AuthLogic and Onboarding contain code distinct to this tutorial.
App.tsx
initialize Firebase, render appAuthLogic.tsx
initialize Doorman, and conditionally render an authentication flow, an onboarding screen, or an authenticated app.Onboarding.tsx
Collect user information if they aren't in the DB yet.
App.tsx
import AuthLogic from './AuthLogic'
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore' // <- if you use Firestore
if (!firebase.apps.length) {
// you can replace this with your firebase config
firebase.initializeApp({
apiKey: 'AIzaSyCn8HyP1tVZiagk-YvZRwjSwKdwQw5Pvng',
authDomain: 'tester-9d8bb.firebaseapp.com',
databaseURL: 'https://tester-9d8bb.firebaseio.com',
projectId: 'tester-9d8bb',
storageBucket: 'tester-9d8bb.appspot.com',
messagingSenderId: '760778283392',
appId: '1:760778283392:web:05cb35d0837c93c6584965',
})
}
export default AuthLogic
This is simple boilerplate code that is no different than normal initialization for Firebase/Doorman.
You can replace the
firebase.initializeApp
config variable with your own firebase config.This tutorial will rely on the
DoormanProvider
implementation instead of withPhoneAuth
. (They both achieve the same thing, as mentioned in the quick example.)First, create a component called AuthLogic.
AuthLogic.tsx
import React from 'react'
const AuthLogic = () => {
return <></>
}
export default AuthLogic
Next, we'll add the Doorman Provider. This provider must wrap your entire app at the root file.
import React from 'react'
import { DoormanProvider } from 'react-native-doorman'
const AuthLogic = () => {
return (
<DoormanProvider publicProjectId="djzlPQFxxzJikNQgLwxN">
{/* Our auth logic will go here next. */}
</DoormanProvider>
)
}
export default AuthLogic
The
AuthGate
updates the state based on whether or not the user is authenticated. import React from 'react'
import { DoormanProvider, AuthGate } from 'react-native-doorman'
const AuthLogic = () => {
return (
<DoormanProvider publicProjectId="djzlPQFxxzJikNQgLwxN">
<AuthGate></AuthGate>
</DoormanProvider>
)
}
export default AuthLogic
AuthGate
accepts a single child: a function that returns a component. It receives the user
and loading
fields as arguments.<AuthGate>
{({ user, loading }) => {
// if loading auth listener
if (loading) return <></>
// if user is not authenticated
if (!user) return <AuthFlow />
// your actual app component, which appears after
// the user has authenticated
return <AfterAuth />
}}
</AuthGate>
Whoa, where did
AuthFlow
come from? That's the Doorman component that lets your users sign in with phone number. AfterAuth
is your normal app component.Our file now looks like this:
AuthLogic.tsx
(or .js
if you don't use TypeScript)import React from 'react'
import { DoormanProvider, AuthGate, AuthFlow } from 'react-native-doorman'
const AuthLogic = () => {
return (
<DoormanProvider publicProjectId="djzlPQFxxzJikNQgLwxN">
<AuthGate>
{({ user, loading }) => {
// if loading auth listener
if (loading) return <></>
// if user is not authenticated
if (!user) return <AuthFlow />
// your actual app component, which appears after
// the user has authenticated
return <AfterAuth />
}}
</AuthGate>
</DoormanProvider>
)
}
export default AuthLogic
Now, on to the code that lets you add your user to the DB.
First, let's add a
userExistsInDb
state variable, whose initial value is false
. Add a checkingIfUserExists
state variable too, which indicates if the DB check is loading or not.const AuthLogic = () => {
const [userExistsInDb, setUserExistsInDb] = useState(false)
const [checkingIfUserExists, setCheckingIfUserExists] = useState(false)
// render code here
}
Next, add a listener callback to the
DoormanProvider
component using its onAuthStateChanged
prop.const AuthLogic = () => {
const [userExistsInDb, setUserExistsInDb] = useState(false)
const [checkingIfUserExists, setCheckingIfUserExists] = useState(false)
const onAuthStateChanged = async (user) => {
if (user) {
const { uid } = user
setCheckingIfUserExists(true)
// user your own function here that calls your database to check
const exists = await checkIfUserExistsInDb(uid)
// if you're using Firestore, it might look like this:
const { exists } = await db.doc(`users/${uid}`).get()
// update the state based on our DB value
setUserExistsInDb(exists)
setCheckingIfUserExists(false)
} else {
// user is not signed in, reset the state to false
setUserExists(false)
setCheckingIfUserExists(false)
}
}
return (
<DoormanProvider
publicProjectId="djzlPQFxxzJikNQgLwxN"
onAuthStateChanged={onAuthStateChanged}
>
...
</DoormanProvider>
)
}
The
onAuthStateChanged
prop is a function that gets called whenever the user signs in or out. It follows the same API from firebase
.The final step is to render an
Onboarding
screen if userExistsInDb
is false
.// 👇 We'll create this in the final step
// you can import your own, too!
import Onboarding from './Onboarding'
...
<AuthGate>
{({ user, loading }) => {
// add checkingIfUserExists to loading condition
if (loading || checkingIfUserExists) return <></>
if (!user) return <AuthFlow />
// If user is authenticated, but doesn't exist in the DB,
// render the onboarding flow.
// We pass it a callback function called onUserAddedToDb
// this function will set userExistsInDb to true
// it gets called after the DB has been updated by <Onboarding />
if (!userExistsInDb) {
return (
<Onboarding
onUserAddedToDb={() => setUserExistsInDb(true)}
/>
)
}
// your actual app component, which appears after
// the user has authenticated
return <AfterAuth />
}}
</AuthGate>
🎉That's it! All that's left is to make the
Onboarding
screen.Here is our final
AuthLogic
screen, in its entirety:import React, { useState } from 'react'
import { DoormanProvider, AuthGate, AuthFlow } from 'react-native-doorman'
import Onboarding from './Onboarding'
import AfterAuth from './AfterAuth'
import { db } from './db'
const AuthLogic = () => {
const [userExistsInDb, setUserExistsInDb] = useState(false)
const [checkingIfUserExists, setCheckingIfUserExists] = useState(false)
return (
<DoormanProvider
onAuthStateChanged={async user => {
if (user) {
const { uid } = user
setCheckingIfUserExists(true)
// 👇 user your own function here that calls your database to check
// const exists = await checkIfUserExistsInDb(uid)
// if you're using Firestore, it might look like this:
const { exists } = await db.doc(`users/${uid}`).get()
// update the state based on our DB value
setUserExistsInDb(exists)
setCheckingIfUserExists(false)
} else {
// user is not signed in, reset the state to false
setUserExistsInDb(false)
setCheckingIfUserExists(false)
}
}}
publicProjectId="djzlPQFxxzJikNQgLwxN"
>
<AuthGate>
{({ user, loading }) => {
// add checkingIfUserExists to loading condition
if (loading || checkingIfUserExists) return <></>
if (!user) return <AuthFlow />
// If user is authenticated, but doesn't exist in the DB,
// render the onboarding flow.
// We pass it a callback function called onUserAddedToDb
// this function will set userExistsInDb to true
// it gets called after the DB has been updated by <Onboarding />
if (!userExistsInDb) {
return (
<Onboarding onUserAddedToDb={() => setUserExistsInDb(true)} />
)
}
// your actual app component, which appears after
// the user has authenticated
return <AfterAuth />
}}
</AuthGate>
</DoormanProvider>
)
}
export default AuthLogic
Note: If you have your own
Onboarding
screen (or React Navigation
stack, you can render it in place of Onboarding
.- If you're using a React Navigation Stack in place of
Onboarding
(assuming it's withv5
), then pass theonUserAddedToDb
function as aparam
to your stack, and call it from your screen usinguseRoute().params.onUserAddedToDb
.
👋Don't forget to call the
onUserAddedToDb
function after successfully adding your user to the database, as seen in line 19 below! If you don't call it, the app won't re-render.Here's an example of a basic
Onboarding
screen:Onboarding.tsx
import React, { useState } from 'react'
import { TextInput, Button, View } from 'react-native'
import { useDoormanUser } from 'react-native-doorman'
const Onboarding = ({ onUserAddedToDb }) => {
const [name, setName] = useState('')
const { uid } = useDoormanUser()
const handleSubmit = async () => {
// Implement your own DB function here
await addUserToDb({ uid, name })
// ...if you're using Firestore, it might look like:
await db.doc(`users/${uid}`).set({ name }, { merge: true })
// Finally, once the user has been added,
// call the callback function from the props.
// 🚨if you forget to call this function, the app won't re-render
onUserAddedToDb()
}
return (
<View style={styles.container}>
<TextInput
placeholder="Enter your name"
value={name}
onChangeText={setName}
/>
<Button
title="Submit name"
onPress={handleSubmit}
/>
</View>
)
}
export default Onboarding
const styles= StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center'
}
})
Here's an example app screen, which you can make in your
AfterAuth.tsx
file:import React from 'react'
import {
Page,
ScreenBackground,
useDoormanUser,
H1,
Paragraph,
} from 'react-native-doorman'
import { Button } from 'react-native'
const AfterAuth = () => {
const { uid, signOut } = useDoormanUser()
return (
<Page
style={{ marginTop: 100, alignItems: 'center' }}
background={() => <ScreenBackground />}
>
<H1 style={{ color: 'white' }}>Welcome to Doorman.</H1>
<Paragraph style={{ color: 'white' }}>
Sign out below, if {`you'd`} like. Your user id is {uid}.
</Paragraph>
<Button title="Sign Out" color="white" onPress={signOut} />
</Page>
)
}
export default AfterAuth
If you're using Firestore as your DB, you'll find examples in this tutorial for how to read and write a user.
For the sake of the tutorial, you can create a
db.ts
file, and populate it with this. You can also set a custom firebaseConfig
from your own Firebase project.import firebase from 'firebase/app'
export const firebaseConfig = {
apiKey: 'AIzaSyCn8HyP1tVZiagk-YvZRwjSwKdwQw5Pvng',
authDomain: 'tester-9d8bb.firebaseapp.com',
databaseURL: 'https://tester-9d8bb.firebaseio.com',
projectId: 'tester-9d8bb',
storageBucket: 'tester-9d8bb.appspot.com',
messagingSenderId: '760778283392',
appId: '1:760778283392:web:05cb35d0837c93c6584965',
}
export const db = !firebase.apps.length
? firebase.initializeApp(firebaseConfig).firestore()
: firebase.app().firestore()
Last modified 2yr ago