Home
> Supabase Subscriptions Just Got Easier

Supabase Subscriptions Just Got Easier

9 min read

Jonathan Gamble

jdgamble555 on Sunday, October 23, 2022 (last modified on Sunday, December 17, 2023)

Channels#

For the moment, subscribing to realtime data in Supabase is very limited, and not easy to use. I personally believe the channels features is unnecessary and a waste of the developers time... for now. Let's not add new feature modules until the current features are adequate... capiche?

If you come from Firebase, you will be very disappointed in the way that you subscribe to realtime data. This is the same for onAuthStateChange and for channels. There are a few problems here.

  1. You have to get the data first, as the Subscription does not return the current data beforehand.
  2. You have to watch each type of change "INSERT, UPDATE, DELETE," in order to see the changes. You have to manually update accordingly in each case.
  3. Only the current change is returned, not the whole data.
  4. The UI is incredibly over-engineered and counterintuitive. Just figuring out how it works takes you at least an hour without examples.
  5. There is a few second delay when starting the subscriptions.
  6. There is only one filter you can use: eq.
  7. There is no way to limit the results.
  8. Perhaps the most important, you cannot use Views with Supabase Channels.
  9. When a group of data is inserted, it doesn't return in bulk, but individually.
  10. There are no optimistic updates, nor persistent offline data capabilities.

Problems 1 - 4 - Clean Code#

I cannot help with the limitations of Supabase, but I did write a package that makes dealing with Subscriptions way easier.

Problems 5 - 9#

These are the current limitations of Supabase. Don't get me wrong, I LOVE SUPABASE, and I am currently using it on this blog: Code.Build. It just seems to me these are problems on the backburner and not at the top of the list to fix. Subscriptions to realtime data is incredibly important for a lot of people. Let's get this up-to-par please. I wrote a list of issues a while back. I finally decided to fix what I could.

This is just not good enough:

	supabaseClient
  .channel('any_string_you_want')
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'movies',
    },
    (payload) => {
      console.log(payload)
    }
  )
  .subscribe()

Problem 10 - Offline & Optimistic#

Okay, so that last one is doable, and someone is working on the caching right now with supabase-cache-helpers.

I also wrote an app to show you how you can do optimistic updates. Basically, you just create an array of your data, and change that array before the subscriptions returns. This is how Firebase's subscriptions are extremally fast. I may integrate this later into j-supabase.

You can also see an example realtime todo app I build with subscriptions and optimistic updates:

j-supabase#

So, I created a simple tree-shakable package. I plan on adding more cool stuff to it later.

Authentication#

First thing is first. Install the package:

	npm i j-supabase

Make sure you have the latest version of Supabase SDK V2:

	npm i @supabase/supabase-js

Authentication now works as expected like it does in Firebase:

	import { authUser, authSession, realtime } from 'j-supabase';

// user
const unsubscribe = authUser(supabase).subscribe(user => console.log(user));

// session
const unsubscribe = authSession(supabase).subscribe(session => console.log(session));

The current data is returned, and you can easily get to the variables without navigating a sub-tree of objects. You can see how it was done before in my previous article.

Realtime Data#

You can get the realtime data as you would expect, the Supabase way:

	// subscribe to a table
const unsubscribe = realtime<Todo>(supabase).from('todos')
  .subscribe(snap => console.log(snap));

// use the one `eq` filter
const unsubscribe = realtime<Todo>(supabase).from('todos').eq('uid', uid)
  .subscribe(snap => console.log(snap));

I do have two optional inputs:

idField

Just in case your primary key is not id:

	const unsubscribe = realtime<Todo>(supabase, { idField: 'user_id' }).from('todos').eq('uid', uid)
  .subscribe(snap => console.log(snap));

schema

You must set your async schema when you declare your use createClient, but you can set your subscriptions schema this way:

	const unsubscribe = realtime<Todo>(supabase, { schema: 'marketing' }).from('todos').eq('uid', uid)
  .subscribe(snap => console.log(snap));

This package is very easy, very clean (I do not use any dependencies), and very useful!

That is pretty much all Supabase can do... for the moment... but I hope to seen new filters soon, and hopefully subscribable Views in the near future..

Possible todo list:

  • auto-resubscribe - while Supabase does automatically re-subscribe, you lose your data. This would keep it.
  • optimistic updates - Optimistic updates would be impossible for all situations, but I may add upsert, insert, update, and delete functions in this package to catch optimistic updates from the subscribed table. TBD.
  • OR Opperators - this would really be multiple subscriptions to the same table binded together and automatically handled. Same as in operator.

UPDATE 10/30/22 - I have added utility functions and it now automatically updates the data on auto-resubscribe.

UPDATE 2/18/23 - I have added all available filters: eq, neq, lt, lte, gt, gte, in. Please create an issue if it doesn't work. Thanks!

Hope this helps someone,

J


Related Posts

Newsletter

Get updates and the latest coding blog posts!

© 2024 Code.Build