Query Supabase Data with Remix Loaders

Jon Meyers
InstructorJon Meyers
Share this video with your friends

Social Share Links

Send Tweet

The supabase-js package allows us to connect to our Supabase project, and easily query and mutate data. In this lesson, we install supabase-js, set up environment variables for SUPABASE_URL and SUPABASE_ANON_KEY, and create a Supabase client to use across our application.

Additionally, we look at writing an RLS policy to enable read access to our messages table, use our Supabase client to select all messages, and display them in our Remix app on load.

Code Snippets

Install supabase-js

npm i @supabase/supabase-js

Use a Loader function to fetch data

export const loader = async () => {
  return null;
};

Fetch data with Supabase Client

const { data } = await supabase.from("messages").select();

Full component

import { useLoaderData } from "@remix-run/react";
import supabase from "utils/supabase";

export const loader = async ({}) => {
  const { data } = await supabase.from("messages").select();
  return { data };
};

export default function Index() {
  const { data } = useLoaderData();
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

Enable read access with RLS policy

create policy "users can read messages" ON "public"."messages"
as permissive for select
to public
using (true);

SQL code snippets can be run against your Supabase database by heading over to your project's SQL Editor, pasting them into a new query, and clicking RUN.

Resources

Instructor: [0:00] We want to display the messages from Supabase on our landing page here in our Remix application. Let's start by quitting our development server and typing npm I or install at Supabase/Supabase-JS. [0:16] Once that's finished, we want to create a new file to hold our environment variables. Let's make sure that this is at the root of our project, and its name is going to be .env. This is already been added to our gitignore file. And so, we don't need to worry about these values being committed to GitHub.

[0:32] In this file, we want a Supabase URL and a Supabase anon key. These two values can be found in our Supabase dashboard under settings and API. You'll see we've got our URL here and our public anon key.

[0:51] We now want to create a folder called utils that should also be at the root-most point of our application. In that, we want a file called supabase.ts. Let's import the createClient function from @supabase/supabase-js. Make the default export from this file a call to createClient, passing it process.env.SUPABASE_URL and our SUPABASE_ANON_KEY.

[1:21] TypeScript is telling us that this value might not exist. We can add an exclamation mark to say these values will definitely exist in all of the environments. Let Supabase throw a runtime error if these don't exist.

[1:35] Back over in index.tsx, we can import our new supabase client. Export a loader function to fetch data from Supabase. We can say const data will be the value we get back from Supabase when we call supabase.from('messages') table. We want to select all of the columns and then return this data from our loader.

[1:58] We can then access this data in our component by calling the useLoaderData hook, which we get from @remix-run/react. We can then render out this data instead of our h1. If you haven't seen this before, this just allows us to pretty-print out a big JSON object to the page.

[2:16] If we run our development server again and then refresh the browser, we'll see that we're getting back an empty array. This might seem like an error because we know that there are two messages in our Supabase database. If we open up the console, go over to the Network tab, and refresh the page, we'll see that all of these status codes look like they were successful requests.

[2:37] The reason for this is back over in our Supabase database, we enabled low-level security for our messages table. This will automatically deny all database actions.

[2:48] Any requests to select insert update or delete. If we want to enable one of these actions for our messages table, we need to write a low-level security policy. We can do that by clicking this button or heading over to authentication and then policies.

[3:02] Now, we want to click new policy. Now, there are some templates for common policies that you might want to write, but we're going to click full customization and write this from scratch. Our policy name is going to be allow users to read messages and we want to allow the select operation.

[3:18] We're going to leave the default for target roles which will be public. Then under our using expression, we just need to give it an expression that evaluates to either 1 or to either allow this action or continue denying it. If we just put in the value 1 then this is always going to enable that select action.

[3:36] Let's click review which is going to show us the SQL that's going to be run against our database and we can click save policy to run that SQL. Now, if we go back to our application and refresh, we can see that our Remix application is correctly displaying the messages from Supabase.