codex-lv3-may-2025

Connecting Supabase to Your React App

Learn how to integrate your Supabase database with a React application to read and write data from your frontend.

Prerequisites:

Time Required: 20-30 minutes


What You’ll Learn

By the end of this guide, you’ll be able to:


Step 1: Get Your Supabase Connection Files

Supabase provides starter code to help you connect quickly!

Go to your Supabase project dashboard and click on the “Connect” tab in the left sidebar.

Show Me Supabase Connect Tab

What you’ll find:


Step 2: Select Your Project Framework Settings

In the Connect tab, select “React” or “JavaScript” as your framework.

Show Me Select Framework Settings

What happens:

Note: You can choose TypeScript (.ts/.tsx) or JavaScript (.js/.jsx) - both work the same way!


Step 3: Copy the Three Starter Files

Supabase provides three files to get you started. Copy these into your React project.

Show Me Copy Starter Files

The three files you’ll need to modify:

  1. .env.local - Environment variables file
    • Stores your Supabase URL and API key securely
    • Keeps sensitive data out of your code
    • Create in your project root: .env.local
  2. src/utils/supabase.js - Supabase client configuration
    • Creates connection to your database
    • Uses environment variables for API credentials
    • Copy to: src/utils/supabase.js
  3. src/App.jsx - Main React component
    • Shows how to fetch and display data from Supabase
    • Demonstrates useState and useEffect with database
    • Modify your existing App.jsx file

File Structure:

project-root/
├── .env.local           # Environment variables
├── src/
│   ├── utils/
│   │   └── supabase.js  # Supabase client config
│   └── App.jsx          # Main component (modified)
└── package.json

💡 Tip: Create the utils folder first: mkdir src/utils

How to set up:


Step 4: Customize for Your Table Schema

The starter code uses a generic “todos” table. Change it to match your table name and columns. We’ll use “employees” as an example.

Show Me Customize Table Schema

What to change:

  1. In src/App.jsx:
    • Update the table name in your queries (e.g., 'employees', 'products', 'students')
    • Update column names in the .select() query
    • Update the variable names to match your data
    • Change how you display the data in JSX
    • Example: item.taskitem.first_name for different column names

Note: The src/utils/supabase.js file only contains the client configuration and doesn’t need table-specific changes.

Example:

Before (todos):

const { data, error } = await supabase
  .from('todos')
  .select('id, task, completed');

After (employees):

const { data, error } = await supabase
  .from('employees')
  .select('id, first_name, last_name, department');

Step 5: Fix the Import Bug (Important!)

⚠️ Common Bug Alert! There’s a known issue in the Supabase starter code with the import statement.

Show Me Import Bug Fix

The Problem: The starter code uses a named import when it should use a default import, and has the wrong path.

Wrong (from starter code):

import { supabase } from '../utils/supabase'

Correct:

import supabase from './utils/supabase'

Where to fix:

💡 Why? The supabase.js file uses export default, so you need a default import, not a named import.

Fix 2: Add async to Functions Using await

The Problem: Functions that use await must be declared as async. The starter code is missing the async keyword.

Wrong (from starter code):

function getTodos() {
  const { data: todos } = await supabase.from('todos').select()
  // ... rest of function
}

Correct:

async function getEmployees() {
  const { data: employees } = await supabase.from('employees').select()
  // ... rest of function
}

Where to fix:

Fix 3: Use .env.local for Better Security

The Problem: The starter code creates a .env file, but .env.local is more secure.

Recommended change:

Correct .env.local format:

VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key-here

Important:


Step 7: Install Supabase Client Library

Before your code will work, you need to install the Supabase JavaScript client.

In your React project terminal:

npm install @supabase/supabase-js

If using JavaScript (not TypeScript), also install:

npm install tslib

What this does:

Verify installation:


Step 8: Test Your Connection

Now test that everything is working!

Steps:

  1. Start your dev server:
    npm run dev
    
  2. Import and use the data in App.jsx:
    import { useState, useEffect } from 'react';
    import supabase from './utils/supabase';
       
    function App() {
      const [data, setData] = useState([]);
         
      useEffect(() => {
        async function fetchData() {
          const { data, error } = await supabase
            .from('employees')
            .select('*');
             
          if (error) {
            console.error('Error:', error);
          } else {
            setData(data);
          }
        }
        fetchData();
      }, []);
         
      return (
        <div>
          <h1>Employee Directory</h1>
          {data.map((employee) => (
            <div key={employee.id}>
              <p>{employee.first_name} {employee.last_name}</p>
            </div>
          ))}
        </div>
      );
    }
       
    export default App;
    
  3. Check your browser:
    • Open http://localhost:5173
    • You should see your data from Supabase!
    • Check the console (F12) for any errors

Debugging:


Common Patterns

Fetching All Data

// In your React component or utils file
async function getAllItems() {
  const { data, error } = await supabase
    .from('your_table_name')
    .select('*');  // * means all columns
    
  if (error) {
    console.error('Error fetching data:', error);
    return [];
  }
  
  return data;
}

Fetching Filtered Data

// Get items matching criteria
async function getEmployeesByDepartment() {
  const { data, error } = await supabase
    .from('employees')
    .select('*')
    .eq('department', 'Engineering');  // Only Engineering employees
    
  if (error) {
    console.error('Error:', error);
    return [];
  }
  
  return data;
}

Inserting New Data

// Create a new row
async function createEmployee(firstName, lastName, department) {
  const { data, error } = await supabase
    .from('employees')
    .insert([
      { first_name: firstName, last_name: lastName, department: department }
    ])
    .select();
    
  if (error) {
    console.error('Error creating employee:', error);
    return null;
  }
  
  return data;
}

Using in React Component

function EmployeeForm() {
  const [employees, setEmployees] = useState([]);
  
  async function handleSubmit(e) {
    e.preventDefault();
    
    // Get form data using event.target
    const formData = new FormData(e.target);
    const firstName = formData.get('firstName');
    const lastName = formData.get('lastName');
    const department = formData.get('department');
    
    // Create new employee
    const newEmployee = await createEmployee(firstName, lastName, department);
    
    // Refresh the list
    const { data } = await supabase
      .from('employees')
      .select('*');
    setEmployees(data);
    
    // Clear form
    e.target.reset();
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <input 
        name="firstName"
        placeholder="First Name..."
      />
      <input 
        name="lastName"
        placeholder="Last Name..."
      />
      <input 
        name="department"
        placeholder="Department..."
      />
      <button type="submit">Add Employee</button>
    </form>
  );
}

🆘 Troubleshooting

Issue: “Could not resolve ‘tslib’” error

Solution:

Example Error:

✘ [ERROR] Could not resolve "tslib"
node_modules/@supabase/storage-js/dist/module/lib/fetch.js:1:26:
1 │ import { __awaiter } from "tslib";
  ╵                           ~~~~~~~

Issue: “Outdated Optimize Dep” error after installing packages

Solution:

Example Error:

GET http://localhost:5173/node_modules/.vite/deps/@supabase... net::ERR_ABORTED 504 (Outdated Optimize Dep)

Issue: “supabase is not defined”

Solution:

Issue: No data showing / Empty array

Solution:

Issue: Can’t insert data

Solution:

Issue: CORS errors

Solution:

Issue: “Anonymous access is disabled”

Solution:


🎯 Key Concepts

Supabase Client:

Async/Await:

Query Methods:

Error Handling:


📚 Resources

Official Documentation:

Video Tutorials:

React Patterns:


🚀 Next Steps

Once you have data displaying:

  1. Add Create Functionality:
    • Build a form to add new rows
    • Use .insert() to save data
    • Refresh the list after creating
  2. Add Update Functionality:
    • Add edit buttons to items
    • Use .update() to modify rows
    • Show updated data immediately
  3. Add Delete Functionality:
    • Add delete buttons
    • Use .delete() to remove rows
    • Update the list after deletion
  4. Explore Real-time:
    • Subscribe to changes with .on('INSERT')
    • Auto-update when data changes
    • Build collaborative features

✅ Success Checklist

You’ve successfully connected React to Supabase if you can:


💡 Best Practices

Organization:

Error Handling:

Performance:

Security:


Congratulations! You can now build full-stack React applications with a real database! 🎉


Attribution: This guide was created with assistance from Claude AI (Anthropic) to provide clear, step-by-step instructions for connecting React to Supabase.