DEV Community

Cover image for Realtime Subscriptions using Vue + Supabase
Ademílson F. Tonato
Ademílson F. Tonato

Posted on

Realtime Subscriptions using Vue + Supabase

Hey, if you don't know what I'm talking about, you should read my first article through this link.

Context:

We've created a microblog using Vue + Supabase (an open-source Firebase alternative). Today we're going to show a new publication whenever it is inserted into the database.


Our starting point will be the code created in the last article, you can access the repository to view the source code.

Our main branch of git, is called main, we will create a branch from this called feat/add-subscription (you can access it here), we can do this using the following command on the command line:

// git clone git@github.com:ftonato/vue-supabase-microblog.git
// cd vue-supabase-microblog

git checkout -b feat/add-subscription
Enter fullscreen mode Exit fullscreen mode

By browsing the documentation, we can find out how to subscribe in detail.

A subscription is like to watch changes in realtime in your database. This means that each time an event (INSERT, UPDATE, DELETE, *) happens, we can trigger a function.

E.g.:

const mySubscription = supabase
  .from('*')
  .on('*', payload => {
    console.log('Change received!', payload)
  })
  .subscribe()
Enter fullscreen mode Exit fullscreen mode

In the example above we are saying to our application: "Whenever an event happens, whatever the table, print the payload information using a console.log.

What we will do is similar to the example, with two different details:

  1. We will only watch from one table (posts).
  2. We only want to watch at the INSERT event.

In our List.vue file, we will create a new variable called subscriptionPosts and a method subscribePosts.

We will call this method when assembling (mounted) our component and its responsibility should be:

  • Whenever a new record is inserted in this table, add it to the posts variables (local variable that stores the publications).

Below our code with the implementation:

<template>
  <section class="px-2 pt-16 pb-6 bg-white md:px-0">
    <div class="container items-center max-w-6xl px-8 mx-auto xl:px-5">
      <template v-for="(post, index) in posts">
        <list-item
          :key="`post-${index}`"
          :id="post.id"
          :title="post.title"
          :description="post.description"
        />
      </template>
    </div>
  </section>
</template>

<script>
import ListItem from "./ListItem";
import DatabaseService from "../Database.service";

export default {
  name: "List",
  components: {
    ListItem,
  },
  data: () => ({
    posts: [],
    database: null,
    subscriptionPosts: undefined,
  }),
  created() {
    const database = new DatabaseService();
    this.database = database.getInstance();
  },
  async mounted() {
    await this.fetchPosts();
    this.subscribePosts();
  },
  methods: {
    async fetchPosts() {
      let { error, data } = await this.database
        .from("posts")
        .select()
        .order("id");
      if (error) {
        console.error(error);
        return;
      }

      this.setPosts(data);
    },
    setPosts(posts) {
      this.posts = posts;
    },
    subscribePosts() {
      this.subscriptionPosts = this.database
        .from("posts")
        .on("INSERT", (message) => {
          if (message.new) {
            this.posts.push(message.new);
          }
        })
        .subscribe();
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

This is the code required for realtime subscription to be implemented.

Are you ready to see the result?

Realtime Subscription

Definitely spectacular!


What was done above would be enough, but let's take a little care of our application and remove the subscription in the dismantling (destroyed) of our component.

Always unsubscribe, when new values in the subscribed stream is no more required or don't matter, it will result in way less number of triggers and increase in performance in a few cases.

We create a method called unsubscribePosts which will be responsible for removing the subscription.

<template>
  <section class="px-2 pt-16 pb-6 bg-white md:px-0">
    <div class="container items-center max-w-6xl px-8 mx-auto xl:px-5">
      <template v-for="(post, index) in posts">
        <list-item
          :key="`post-${index}`"
          :id="post.id"
          :title="post.title"
          :description="post.description"
        />
      </template>
    </div>
  </section>
</template>

<script>
import ListItem from "./ListItem";
import DatabaseService from "../Database.service";

export default {
  name: "List",
  components: {
    ListItem,
  },
  data: () => ({
    posts: [],
    database: null,
    subscriptionPosts: undefined,
  }),
  created() {
    const database = new DatabaseService();
    this.database = database.getInstance();
  },
  async mounted() {
    await this.fetchPosts();
    this.subscribePosts();
  },
  destroyed() {
    this.unsubscribePosts();
  },
  methods: {
    async fetchPosts() {
      let { error, data } = await this.database
        .from("posts")
        .select()
        .order("id");
      if (error) {
        console.error(error);
        return;
      }

      this.setPosts(data);
    },
    setPosts(posts) {
      this.posts = posts;
    },
    subscribePosts() {
      this.subscriptionPosts = this.database
        .from("posts")
        .on("INSERT", (message) => {
          if (message.new) {
            this.posts.push(message.new);
          }
        })
        .subscribe();
    },
    unsubscribePosts() {
      this.database.removeSubscription(this.subscriptionPosts);
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

That's all Folks!

Think of the power that this brings to an application and as I said in the last publication: Let your imagination guide you and explore new horizons.

If you are interested in the source code of the project we created, go to the project directory on GitHub and implement even more exciting things, such as:

If you have any question, do not hesitate to contact me (ademilsonft@outlook.com / @ftonato or the Supabase team).

Top comments (5)

Collapse
 
jdriesen profile image
Johnny Driesen • Edited

Amazing post. Thanks for sharing your knowledge with us.
Just one small remark (might be a new feature in SupaBase ...)
Don't forget to switch on "table replication"...
You can find this in the SupaBase GUI, under "Database" - "Replication".
On the righthand side, click on "Tables"
Next, select the tables you want to set as "realtime", and you're done :)

Collapse
 
jupiteris profile image
Jupiter Programmer

In your opinion, which is more efficient between firebase & spabase?
query speed, cost, etc...

Collapse
 
ftonato profile image
Ademílson F. Tonato

Hey @jupiteris ,

In my opinion, comparing a consolidated database maintained by a company the size of Google with another tool, a new one maintained by the community, is quite difficult.

As we all know, so far, nothing has come close to what Firebase offers (until today)…

Despite the fact that Supabase is still in beta (at the time of writing this), already, it features quite a strong feature-set that takes on some of Firebase' most appealing features like the realtime database, easy setup, and faster workflow (and I read it as a promising alternative).

Collapse
 
itscasey profile image
Casey 💎

Nice! It's cool seeing a Firebase alternative in action.

Are you affiliated with Supabase?

Collapse
 
ftonato profile image
Ademílson F. Tonato

Hey @ioscasey ,

The alternative is really incredible!

I am not affiliated with them, I am just a developer who liked the project, sent several pull requests and decided to share materials to spread the excellent work the team has been doing 👾