Published on
🍵 4 min read

How to setup Supabase in React ? And Some Useful Tips

Authors

Photo

Overview

How to Set Up Supabase in React?

Target Audience

I've aimed this article at people who want to learn about React and Supabase.

Learning Objectives

After completing this article, you will know how to do the following:

  • Create a React application
  • Set up Supabase
  • Fetch data from Supabase
  • Perform CRUD operations in Supabase

What is Supabase?

Supabase is an open-source alternative to Firebase. Start your project with a PostgreSQL database, authentication, instant APIs, real-time subscriptions, and storage.

The key difference between Firestore and Supabase is that Firestore is a NoSQL database, whereas Supabase uses a relational database.

Project Setup

You can check out the Supabase official documentation for project setup. You need to create a project in the Supabase dashboard. There are multiple setup documents for different frameworks, but in this article, I will focus on React.

Create a Project

  1. Go to app.supabase.com.
  2. Click on "New Project."
  3. Enter your project details.
  4. Wait for the new database to launch.

Building the Application

Follow these steps to build the application.

1. Create a React Application

npx create-react-app supabase-react
cd supabase-react

2. Install the Supabase JavaScript Library

npm install @supabase/supabase-js

3. Add Environment Variables to the .env File

You can obtain these variables from the Supabase dashboard.

REACT_APP_SUPABASE_URL=YOUR_SUPABASE_URL
REACT_APP_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY

4. Create the Supabase Client

import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.REACT_APP_SUPABASE_URL
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY

export const supabase = createClient(supabaseUrl, supabaseAnonKey)

You can use this client for authorization, fetching, or mutating data from the database, etc.

5. Create a Service

We will create a service called dummyService where we implement CRUD functions using Supabase operations. We can reference this service from other components to avoid code duplication in our project.

Create Function

async function Create(id, name) {
  let response = await supabase // This is our client
    .from('dummy')
    .insert({
      id: id,
      name: name,
    })
  return response
}

As you can see, for the create operation, we use the insert operation from Supabase.

Read Function

async function Get(name) {
  let response = await supabase // This is our client
    .from('dummy')
    .select('*')
    .eq('name', name)
  return response
}

Update Function

async function Update(id, name) {
  let response = await supabase // This is our client
    .from('dummy')
    .update({ name: name })
    .match({ id: id })

  return response
}

Delete Function

async function Delete(id) {
  let response = await supabase // This is our client
    .from('dummy')
    .delete()
    .match({ id: id })

  return response
}

We can create a service that contains these methods, and when we want to use it, we can import this service. Creating a service for a specific domain is important because it prevents code duplication in our project, making it easier to maintain as the codebase grows.

Example Use Case

import { dummyService } from ".../somewhere";
...
var item = dummyService.Get("name");
return (
  <p>{item}</p>
);
...

Sometimes we want to fetch data before rendering a page. In such scenarios, we can use the useEffect and useState hooks in React. We can call our service functions inside the useEffect hook, and we can create a state for the loading status of our page.

Here is an example use case:

function AnExampleComponent() {
  const [loading, setLoading] = useState(true);
  const [items, setItems] = useState(null);

  const getDataFromService = async (name) => {
    setLoading(true);
    let { data } = await dummyService.Get(name);
    if (data) setItems(data);
    setLoading(false);
  };

  useEffect(() => {
    getDataFromService("stuff");
  }, []);

  return (
    ...
  );
}

As shown in the example, we create loading states for fetching data. This state indicates if the service call has completed. If the request is still in progress or takes a long time, we can show the loading state to improve user experience. We can also handle other states from the service, like error. If an error occurs, we can display that information in the UI if needed.