JSTAcademy
0 XP
Dashboard
Crash Courses
Real-time Subscriptions
10 min
Masters+175 XP
Crash Courses · Masters

Real-time Subscriptions

Build live features with Supabase Realtime — presence, broadcast, and Postgres changes.
10 min read+175 XP on completionCert: Supabase Crash Course
Tap any word in the text below to start reading from there.

Real-time Subscriptions

Supabase Realtime lets you subscribe to database changes over WebSockets. UIs update live without polling.

Subscribe to Table Changes

'use client'
import { useEffect, useState } from 'react'
import { createClient } from '@/lib/supabase/client'

function LiveCourseList() {
  const [courses, setCourses] = useState<Course[]>([])
  const supabase = createClient()

  useEffect(() => {
    // Initial load
    supabase
      .from('courses')
      .select('*')
      .then(({ data }) => setCourses(data ?? []))

    // Subscribe to changes
    const channel = supabase
      .channel('courses-changes')
      .on(
        'postgres_changes',
        { event: '*', schema: 'public', table: 'courses' },
        (payload) => {
          if (payload.eventType === 'INSERT') {
            setCourses(prev => [...prev, payload.new as Course])
          }
          if (payload.eventType === 'DELETE') {
            setCourses(prev => prev.filter(c => c.id !== payload.old.id))
          }
          if (payload.eventType === 'UPDATE') {
            setCourses(prev => prev.map(c => c.id === payload.new.id ? payload.new as Course : c))
          }
        }
      )
      .subscribe()

    return () => { supabase.removeChannel(channel) }
  }, [])

  return <CourseList courses={courses} />
}

Presence (Online Users)

useEffect(() => {
  const channel = supabase.channel('course-room')

  channel
    .on('presence', { event: 'sync' }, () => {
      const state = channel.presenceState()
      const onlineCount = Object.keys(state).length
      setOnlineUsers(onlineCount)
    })
    .subscribe(async (status) => {
      if (status === 'SUBSCRIBED') {
        await channel.track({ user_id: userId, online_at: new Date().toISOString() })
      }
    })

  return () => { supabase.removeChannel(channel) }
}, [])
0%