DEV Community

loading...
Cover image for Realtime Subscriptions using Vue + Supabase

Realtime Subscriptions using Vue + Supabase

ftonato profile image Ademílson F. Tonato ・4 min read

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).

Discussion (4)

pic
Editor guide
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 Author

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 Author

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 👾