Published on

How to setup Supabase in React ? And Some Useful Tips

Authors

How to setup 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
  • Setup Supabase
  • Fetch data from Supabase
  • Make CRUD operations in Supabase

What is Supabase ?

Supabase is an open source Firebase alternative. Start your project with a Postgres Database, Authentication, instant APIs, Real-time subscriptions and Storage.

The difference between Firestore database and Supabase Postgres database is that Firestore is NoSQL database whereas Supabase is relational database.

Project set up

You can check out the Supabase official documentation for project setup. You have to create a project in Supabase dashboard. And there is multiple setup documentations for different frameworks but in this article i will write about 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

Take the following steps to build the application.

1 - Create react application

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

2 - Install supabase-js library

npm install @supabase/supabase-js

3 - Add environment variables to the .env file.

You can get these variables from Supabase dashboard.

REACT_APP_SUPABASE_URL=YOUR_SUPABASE_URL
REACT_APP_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY

4 - Create 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)

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

5- Create a service

We will create a service called dummyService where we create crud functions using Supabase operations. And we can reference this service from other components to use it, so we don't make duplicate code 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 create operation we use 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
}

So 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 doesn't allow us to make duplicate code in our project, so as the code base goes bigger it is easier to maintain.

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 this kind of scenarios, we can use useEffect and useState hooks in React. We can call our service functions inside useEffect hook, and we can create a state for loading state of our page

An example use case for this shown below:

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


	let getDataFromService = async (name) => {
		setLoading(true)
		let { data } = await dummyService.Get(name);
		if(data) setItems(data);
		setLoading(false)
	}
	useEffect(() => {
		getDataFromService("stuff")
	}, [])
	return(
	...
	)
}

As you can see from the example, we create loading states for fetching data. This state will give us for information about service call ended or not. If we don't finish the service request, or it can take long time. We can show the loading state for better user experience. Or we can handle the other states that comes from our service such as error. So if an error occurs in our service function, we can show that information to the UI if necessary.