Realtime subscriptions are a cornerstone of modern, dynamic applications. They allow your frontend to receive instant updates from your Supabase backend whenever data changes in your database. This means no more manual polling or refreshing – your users will see changes as they happen, creating a truly interactive experience. In this section, we'll walk through setting up your very first realtime subscription.
The core of Supabase's realtime functionality lies within its realtime client. You'll use this to connect to your Supabase project and subscribe to specific database tables.
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'YOUR_SUPABASE_URL'
const supabaseAnonKey = 'YOUR_SUPABASE_ANON_KEY'
const supabase = createClient(supabaseUrl, supabaseAnonKey)Now, let's imagine you have a 'todos' table in your Supabase database, and you want to display these todos to your users and update them in real-time. To subscribe to changes in the 'todos' table, you'll use the from() method followed by on().
const channel = supabase.channel('todos-channel')
.on('postgres_changes', {
event: '*', // Listen for all events: INSERT, UPDATE, DELETE
schema: 'public', // Your database schema
table: 'todos'
}, (payload) => {
console.log('Change received!', payload)
// Here, you would update your UI based on the payload
})
.subscribe()Let's break down the on() method:
'postgres_changes': This is the event type that Supabase emits for database changes. You can also listen for other event types like'presence'.{ event: '*', schema: 'public', table: 'todos' }: This is the filter object.event: '*'tells Supabase to send you notifications for any change (INSERT, UPDATE, DELETE) on the specified table. You can also specify individual events like'INSERT'or'UPDATE'.schema: 'public'is the name of your database schema. Usually, it's 'public' unless you've configured otherwise.table: 'todos'is the name of the table you want to monitor for changes.
(payload) => { ... }: This is the callback function that will be executed every time a change matching your filter occurs. Thepayloadobject contains detailed information about the change, including the new record (for INSERT and UPDATE), the old record (for UPDATE and DELETE), and the type of event.
The .subscribe() method at the end establishes the connection to the realtime channel. You'll receive a channel object back, which is useful for managing your subscriptions.
When a change occurs in your 'todos' table, the payload object will look something like this (for an INSERT event):
{
event: 'INSERT',
schema: 'public',
table: 'todos',
new: {
id: 1,
task: 'Learn Supabase realtime',
is_complete: false,
created_at: '2023-10-27T10:00:00.000Z'
},
old: {},
commit_timestamp: '2023-10-27T10:05:00.000Z'
}And for a DELETE event:
{
event: 'DELETE',
schema: 'public',
table: 'todos',
new: {},
old: {
id: 1,
task: 'Learn Supabase realtime',
is_complete: false,
created_at: '2023-10-27T10:00:00.000Z'
},
commit_timestamp: '2023-10-27T10:10:00.000Z'
}Inside your callback, you'll want to process this payload to update your application's state. For example, if it's an 'INSERT', you'd add the new todo to your list. If it's a 'DELETE', you'd remove the todo. If it's an 'UPDATE', you'd find the existing todo and modify it.
It's important to remember to unsubscribe when your component unmounts or your application is closing to prevent memory leaks and unnecessary connections. You can do this using the unsubscribe() method on the channel object.
channel.unsubscribe()Setting up realtime subscriptions is a powerful way to make your applications feel alive and responsive. By following these steps, you've taken a significant leap in building dynamic and engaging user experiences with Supabase.