Use Supabase Auth with React Native
Learn how to use Supabase Auth with React Native
Create a new Supabase project
Launch a new project in the Supabase Dashboard.
Your new database has a table for storing your users. You can see that this table is currently empty by running some SQL in the SQL Editor.
SQL_EDITOR
1select * from auth.users;
Create a React app
Create a React app using the create-expo-app
command.
Terminal
1npx create-expo-app -t expo-template-blank-typescript my-app
Install the Supabase client library
Install supabase-js
and the required dependencies.
Terminal
1cd my-app && npx expo install @supabase/supabase-js @react-native-async-storage/async-storage @rneui/themed react-native-url-polyfill
Set up your login component
Create a helper file lib/supabase.ts
that exports a Supabase client using your Project URL and key.
Changes to API keys
Supabase is changing the way keys work to improve project security and developer experience. You can read the full announcement, but in the transition period, you can use both the current anon
and service_role
keys and the new publishable key with the form sb_publishable_xxx
which will replace the older keys.
To get the key values, open the API Keys section of a project's Settings page and do the following:
- For legacy keys, copy the
anon
key for client-side operations and theservice_role
key for server-side operations from the Legacy API Keys tab. - For new keys, open the API Keys tab, if you don't have a publishable key already, click Create new API Keys, and copy the value from the Publishable key section.
lib/supabase.ts
1234567891011121314151617181920212223242526272829303132import { AppState, Platform } from 'react-native'import 'react-native-url-polyfill/auto'import AsyncStorage from '@react-native-async-storage/async-storage'import { createClient, processLock } from '@supabase/supabase-js'const supabaseUrl = YOUR_REACT_NATIVE_SUPABASE_URLconst supabaseAnonKey = YOUR_REACT_NATIVE_SUPABASE_PUBLISHABLE_KEYexport const supabase = createClient(supabaseUrl, supabaseAnonKey, { auth: { ...(Platform.OS !== "web" ? { storage: AsyncStorage } : {}), autoRefreshToken: true, persistSession: true, detectSessionInUrl: false, lock: processLock, },})// Tells Supabase Auth to continuously refresh the session automatically// if the app is in the foreground. When this is added, you will continue// to receive `onAuthStateChange` events with the `TOKEN_REFRESHED` or// `SIGNED_OUT` event if the user's session is terminated. This should// only be registered once.if (Platform.OS !== "web") { AppState.addEventListener('change', (state) => { if (state === 'active') { supabase.auth.startAutoRefresh() } else { supabase.auth.stopAutoRefresh() } })}
Create a login component
Let's set up a React Native component to manage logins and sign ups.
components/Auth.tsx
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283import React, { useState } from 'react'import { Alert, StyleSheet, View } from 'react-native'import { supabase } from '../lib/supabase'import { Button, Input } from '@rneui/themed'export default function Auth() { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [loading, setLoading] = useState(false) async function signInWithEmail() { setLoading(true) const { error } = await supabase.auth.signInWithPassword({ email: email, password: password, }) if (error) Alert.alert(error.message) setLoading(false) } async function signUpWithEmail() { setLoading(true) const { data: { session }, error, } = await supabase.auth.signUp({ email: email, password: password, }) if (error) Alert.alert(error.message) if (!session) Alert.alert('Please check your inbox for email verification!') setLoading(false) } return ( <View style={styles.container}> <View style={[styles.verticallySpaced, styles.mt20]}> <Input label="Email" leftIcon={{ type: 'font-awesome', name: 'envelope' }} onChangeText={(text) => setEmail(text)} value={email} placeholder="email@address.com" autoCapitalize={'none'} /> </View> <View style={styles.verticallySpaced}> <Input label="Password" leftIcon={{ type: 'font-awesome', name: 'lock' }} onChangeText={(text) => setPassword(text)} value={password} secureTextEntry={true} placeholder="Password" autoCapitalize={'none'} /> </View> <View style={[styles.verticallySpaced, styles.mt20]}> <Button title="Sign in" disabled={loading} onPress={() => signInWithEmail()} /> </View> <View style={styles.verticallySpaced}> <Button title="Sign up" disabled={loading} onPress={() => signUpWithEmail()} /> </View> </View> )}const styles = StyleSheet.create({ container: { marginTop: 40, padding: 12, }, verticallySpaced: { paddingTop: 4, paddingBottom: 4, alignSelf: 'stretch', }, mt20: { marginTop: 20, },})
Add the Auth component to your app
Add the Auth
component to your App.tsx
file. If the user is logged in, print the user id to the screen.
App.tsx
123456789101112131415161718192021222324252627import 'react-native-url-polyfill/auto'import { useState, useEffect } from 'react'import { supabase } from './lib/supabase'import Auth from './components/Auth'import { View, Text } from 'react-native'import { Session } from '@supabase/supabase-js'export default function App() { const [session, setSession] = useState<Session | null>(null) useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setSession(session) }) supabase.auth.onAuthStateChange((_event, session) => { setSession(session) }) }, []) return ( <View> <Auth /> {session && session.user && <Text>{session.user.id}</Text>} </View> )}
Start the app
Start the app, and follow the instructions in the terminal.
Terminal
1npm start