Supabase RealTime Event - Value only gets updated on 1 of the 2 places

168 Views Asked by At

For my web app, I've built a credit system where people can redeem their credits to get the 'full' version of something in return.

Scenario: A user uploads an image and gets the upscaled version back only when clicking "Redeem credit for full version".

When the user clicked on that, I want to show directly -1 to the current credits amount. I'm using that number on two places, on a certain page and always in the topbar.

The problem is that when the user redeems one credit, it only updates one of those two values instead of both simultaneously.

Below can you find my credits logic component that is used on two places on the certain page:

import { useUser } from "@/hooks/useUser";
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs";
import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";

const CreditsNummer = () => {
  const { user, userDetails, isLoading } = useUser();
  const supabase = createClientComponentClient();

  const initialvalueCredits =
    userDetails?.credits_pay_per_removal! + userDetails?.credits_subscription!;
  const [userCredits, setUserCredits] = useState(initialvalueCredits);

  useEffect(() => {
    if (isNaN(userCredits) && !isLoading) {
      // Fetch user details to get the missing values
      const creditsPayPerRemoval = userDetails?.credits_pay_per_removal!;
      const creditsSubscription = userDetails?.credits_subscription!;
      const newCredits = creditsPayPerRemoval + creditsSubscription;
      setUserCredits(newCredits);
    }
  }, [userCredits, userDetails, isLoading]);

  useEffect(() => {
    const channel = supabase
      .channel("realtime credits")
      .on(
        "postgres_changes",
        {
          event: "*",
          schema: "public",
          table: "users",
        },
        (payload) => {
          if (
            payload.new &&
            "credits_pay_per_removal" in payload.new &&
            "credits_subscription" in payload.new
          ) {
            // Update userCredits when the event is received
            const newCredits =
              payload.new.credits_pay_per_removal +
              payload.new.credits_subscription;
            setUserCredits(newCredits);
          }
        }
      )
      .subscribe();

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

  if (isLoading) {
    // Return a loading indicator or placeholder until user details are available
    return <p>Loading...</p>;
  }

  return <div>{user ? <>{userCredits}</> : 0}</div>;
};

export default CreditsNummer;

FYI: I have two types of credits, but that is not relevant for now since it is working in one of the places.

Looking forward to your response!

I googled this, but couldn't find this issue. Asked chatgpt, doesn't give me a working solution.

1

There are 1 best solutions below

1
On

You cannot have more than one active realtime channels simultaneously be active within your web app.

The channel names can be literally anything, so remember to always create a unique channel when you open a client in Supabase.

supabase.channel(somethingUniqueHere)