How to Use Supabase in React Native

Supabase can be a strong backend for React Native apps when you want PostgreSQL, SQL, Row Level Security, Auth, Storage, and Edge Functions. The key React Native detail is session persistence: configure storage and URL handling before building screens on top of the Supabase client.
Quick Answerโ
Install @supabase/supabase-js, add a URL polyfill, persist auth sessions with
AsyncStorage, use a publishable key in the app, and protect tables with Row
Level Security. Never put a Supabase secret key or service role key in a React
Native bundle.
If you are comparing with Firebase, read:
Install Supabase for React Nativeโ
yarn add @supabase/supabase-js
yarn add @react-native-async-storage/async-storage react-native-url-polyfill
cd ios && pod install
If you use Expo, follow the Supabase Expo quickstart for package installation. The app code below still applies to the core Supabase client setup.
Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount ๐ฅ
Get the Mega BundleInitialize the Supabase Clientโ
Create lib/supabase.ts:
import { 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 = process.env.EXPO_PUBLIC_SUPABASE_URL;
const supabasePublishableKey =
process.env.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY;
if (!supabaseUrl || !supabasePublishableKey) {
throw new Error('Missing Supabase environment variables');
}
export const supabase = createClient(
supabaseUrl,
supabasePublishableKey,
{
auth: {
...(Platform.OS !== 'web' ? { storage: AsyncStorage } : {}),
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
lock: processLock,
},
}
);
if (Platform.OS !== 'web') {
AppState.addEventListener('change', state => {
if (state === 'active') {
supabase.auth.startAutoRefresh();
} else {
supabase.auth.stopAutoRefresh();
}
});
}
Use the publishable key from your Supabase project settings. The secret key and service role key belong on trusted servers only.
Sign Up and Sign Inโ
export async function signUpWithEmail(email: string, password: string) {
const { data, error } = await supabase.auth.signUp({
email,
password,
});
if (error) {
throw error;
}
return data;
}
export async function signInWithEmail(email: string, password: string) {
const { data, error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) {
throw error;
}
return data;
}
Listen for auth changes once near the app root:
useEffect(() => {
const {
data: { subscription },
} = supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
return () => subscription.unsubscribe();
}, []);
Create a Table with Row Level Securityโ
Example todo table:
create table public.todos (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references auth.users(id) on delete cascade,
title text not null,
completed boolean not null default false,
created_at timestamptz not null default now()
);
alter table public.todos enable row level security;
create policy "Users can read their own todos"
on public.todos
for select
using (auth.uid() = user_id);
create policy "Users can insert their own todos"
on public.todos
for insert
with check (auth.uid() = user_id);
RLS is not optional for client-side apps. The publishable key is expected to be public, so database policies must enforce the real permissions.
Query Data from React Nativeโ
export async function fetchTodos() {
const { data, error } = await supabase
.from('todos')
.select('*')
.order('created_at', { ascending: false });
if (error) {
throw error;
}
return data;
}
export async function addTodo(title: string, userId: string) {
const { data, error } = await supabase
.from('todos')
.insert({ title, user_id: userId })
.select()
.single();
if (error) {
throw error;
}
return data;
}
Storage Notesโ
Supabase Storage can handle profile photos and user uploads, but it needs bucket policies just like database tables need RLS policies. Store metadata in Postgres, keep files in Storage, and use signed URLs when files should not be public.
Useful Referencesโ
- Supabase React Native Auth quickstart
- Supabase Expo React Native quickstart
- Supabase billing docs
- Supabase documentation
- Instamobile Firebase setup docs
Looking for a custom mobile application?
Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.
Get in TouchConclusionโ
Supabase works well in React Native when the client is initialized correctly and the database is protected with Row Level Security. Treat the publishable key as public, persist sessions with AsyncStorage, and keep privileged operations in Edge Functions or another trusted backend.