Fetching data from Supabase

Learn how fetch data from your Supabase database in Makerkit and Next.js

When fetching data from the Supabase Postgres Database, we use the Supabase JS client.

To make data-fetching from Supabase more reusable, our convention is to create a custom React hook for each query we make.

For example, let's take a look at the hook to fetch an organization from Supabase.

First, we want to write a query that receives two parameters:

  1. a Supabase client interface
  2. an organization ID
organizations/queries.ts
export function getOrganizationById(
  client: Client,
  organizationId: number
) {
  return client
    .from('organizations')
    .select(`
      id,
      name,
      logoURL: logo_url
    `)
    .eq('id', organizationId)
    .throwOnError()
    .single();
}

It's important that we pass the client as a parameter so that we can use the function in both the browser and the server.

Now, if we want to use a React Hook to fetch the organization from one of our components, we can use the useSWR hook from swr:

import useSupabase from '~/core/hooks/use-supabase';
import { getOrganizationById } from '~/lib/organizations/database/queries';
import useSWR from 'swr';
 
function useOrganizationQuery(
  organizationId: number
) {
  const client = useSupabase();
  const key = ['organization', organizationId];
 
  return useSWR(key, async () => {
    return getOrganizationById(client, organizationId).then(
      (result) => result.data
    );
  });
}
 
export default useOrganizationQuery;

Retrieving data using a React hook

Now that we have a hook to fetch an organization, we can use it in our components to retrieve the data.

import { useOrganizationQuery } from './use-organization-query';
 
function OrganizationCard({ organizationId }) {
  const {
    data: organization,
    isLoading,
    error
  } = useOrganizationQuery(organizationId);
 
  /* data is loading */
  if (isLoading) {
    return <div>Loading...</div>
  }
 
  /* request errored */
  if (error) {
    return <div>Error!</div>
  }
 
  /* request successful, we can access "organization" */
  return <div>{organization.name}</div>;
}

Retrieving data from the server

When we want to fetch data from the server, we can import a server Supabase client and use it to fetch data.

We can add a Next.js route route.ts to fetch the data. For example, let's create a route to fetch an organization by ID at app/api/organizations/[organizationId]/route.ts

export async function GET(request: NextRequest) {
  const client = getSupabaseServerClient();
 
  const currentOrganizationId = Number(
    await parseOrganizationIdCookie(cookies())
  );
 
  try {
    const { data } = await getOrganizationById(client, organizationId);
 
    return NextResponse.json(data);
  } catch (error) {
    return throwInternalServerErrorException();
  }
}

When you want to ensure your data is rendered on the server, you should ensure you're loading the data using the loader function. Then, you can co-ordinate data re-fetching on the client when the data changes using useSubmit or useFetcher.

When the data is only fetched on the client, you can use useSWR to fetch the data and re-fetch the stale queries.


Subscribe to our Newsletter
Get the latest updates about React, Remix, Next.js, Firebase, Supabase and Tailwind CSS