Supabase with React for Beginners

 


Table of Contents

React Authentication with Supabase

  1. Intro & Demo
  2. Setting Up React Project
  3. Creating SignUp Form
  4. SignUp User
  5. Route Between Pages
  6. Log the user in
  7. Navigate To Homepage
  8. Logout

React CRUD Operations with Supabase

  1. Intro
  2. Setup React and Supabase
  3. Fetch Users (READ)
  4. Create User (CREATE)
  5. Delete User (DELETE)
  6. Update User (UPDATE)

1 Setup React Project

Create project on github.
CD to Project folder local.
git clone https://gihube.com/YOURREPO.GIT

Git Workflow Example: Initial Commit and Push

Initial Status Check

PS C:\Users\capta\proj\React-Auth-Supa> git status
On branch main
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
nothing added to commit but untracked files present (use "git add" to track)

Adding Files and Committing

PS C:\Users\capta\proj\React-Auth-Supa> git add .
PS C:\Users\capta\proj\React-Auth-Supa> git commit -m "docs: readme.md file"
[main (root-commit) 04e1abe] docs: readme.md file
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

Pushing to Remote

PS C:\Users\capta\proj\React-Auth-Supa> git push -u origin main
Enumerating objects: 3, done.
Writing objects: 100% (3/3), 261 bytes | 261.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

Updating the README

PS C:\Users\capta\proj\React-Auth-Supa> git add .
PS C:\Users\capta\proj\React-Auth-Supa> git commit -m "docs: added description"
[main 3bf09c5] docs: added description
 1 file changed, 1 insertion(+)
PS C:\Users\capta\proj\React-Auth-Supa> git push
Enumerating objects: 5, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/krashautomation/React-Auth-Supa.git
   04e1abe..3bf09c5  main -> main

Key Takeaways

  • Initial Setup: Shows the complete workflow from first commit to push
  • Conventional Commits: Using docs: prefix for documentation changes
  • Branch Tracking: Setting upstream with -u origin main

2. Creating your Vite Project


Adding Vite to an Existing Project? Don't Miss This Critical Detail

That innocent-looking dot at the end of your Vite command changes everything. Let's break it down:

🆕 Without the Dot

npm create vite@latest

→ Creates a new folder called vite-project

→ Perfect for fresh projects

your-project/
  └── vite-project/ ← Brand new folder
      ├── src/
      └── package.json

🔄 With the Dot

npm create vite@latest .

→ Injects Vite directly into your current folder

→ What you want for existing projects

your-project/ ← Vite added here
  ├── src/ (new)
  ├── package.json (merged)
  └── existing-files (kept)

⚠️ Pro Tip

When using the dot version:

  1. Vite may ask to overwrite files
  2. Never blindly accept - manually merge:
    • Keep your existing package.json scripts
    • Preserve custom configs
    • Only add Vite-specific changes

🎚 Side-by-Side Comparison

vite@latest vite@latest .
New folder
Modifies current dir
Conflict risk None High

🏁 The Right Choice

For existing projects:

npm create vite@latest .

Then carefully merge files. Your future self will thank you.

(Tip: Use monospace font for code blocks and bright accent colors for commands on dark backgrounds.)

Git Workflow: Multiple File Changes

Option 1: Atomic Commits (Recommended)

Separate commits for logically distinct changes:

# Stage and commit each change separately
git add file1.js
git commit -m "feat: add user authentication"

git add file2.css
git commit -m "style: update button colors"

git add file3.md
git commit -m "docs: correct API examples"

✓ Pros: Clean history, easier debugging
✗ Cons: More steps

Option 2: Single Combined Commit

When changes are related:

# Stage all changes together
git add .
git commit -m "feat: implement login system with styled buttons"

✓ Pros: Faster workflow
✗ Cons: Less granular history

Option 3: Interactive Staging

For mixed changes (some atomic, some combined):

git add -p # Review changes interactively
# For each change:
(y) stage
(n) don't stage
(s) split larger changes

✓ Pros: Maximum control
✗ Cons: Steeper learning curve

Best Practice

"Commit like you're sending a message to your future self debugging at 3AM."
Separate commits when changes serve different purposes, combine when they're part of the same logical change.



3. Creating the Signup Form

React Form Component

This code creates a basic form component in React with three controlled inputs:

function handleChange(event) {
  // Handles input changes (currently empty)
}

return (
  <div>
    <form>
      {/* Full Name Input */}
      <input 
        placeholder='fullname'
        name='fullName' 
        onChange={handleChange} />

      {/* Email Input */}
      <input 
        placeholder='Email'
        name='email'
        onChange={handleChange} />

      {/* Password Input */}
      <input 
        placeholder='Password'
        name='password'
        onChange={handleChange} />
    </form>
  </div>
)

Key Features:

  • Controlled inputs - All form fields use React's onChange handler
  • Empty handler - Currently just a placeholder function (needs state management)
  • Proper naming - Inputs use semantic name attributes
  • Basic structure - Ready for state integration (useState/useReducer)

Next Steps: Add state management to handleChange to store input values and implement form submission.


4. Add Submit Button and Create States for Inputs

React State Object for Form Data

const [formData, setFormData] = useState({
  fullName: '',
  email: '',
  password: ''
})

State Structure Explained:

  • Single source of truth - All form fields managed in one state object
  • Initial empty values - Strings initialized as empty for controlled inputs
  • Destructured assignment - formData contains values, setFormData updates them
  • Consistent naming - Matches the name attributes from your form inputs

Complete Example: Here's how to connect this to your form handler:

function handleChange(event) {
  setFormData({
    ...formData,
    [event.target.name]: event.target.value
  })
}

Key Benefit: This pattern keeps all form data organized together and makes it easy to submit the entire object to an API endpoint later.


5. Setup State Management for Form and View in Console


React Form State Management

State Initialization

const [formData, setFormData] = useState({
  fullName: '',
  email: '',
  password: ''
});

This creates a state object to store all form fields with empty initial values.

Debugging with Console

console.log(formData);

Outputs the current state to browser console. Chrome may recommend:

⚠️ For better React debugging, install:

React Developer Tools

Recommended Next Steps

  • Implement handleChange to update state
  • Add form submission handler
  • Install React DevTools for component inspection

With React DevTools, you can inspect component state and props directly in Chrome's Developer Tools panel.

6. Signup User on Supabase: Authentication Flow

Installing Supabase in a React Project

1. Install Supabase JS Library

Run this command in your project directory:

npm install @supabase/supabase-js

Or if using yarn:

yarn add @supabase/supabase-js

2. Create Supabase Client

Create a new file src/lib/supabaseClient.js:

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

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

export const supabase = createClient(supabaseUrl, supabaseKey)

3. Configure Environment Variables

Create a .env file in your project root:

REACT_APP_SUPABASE_URL=your-project-url
REACT_APP_SUPABASE_ANON_KEY=your-anon-key

Find these values in your Supabase project settings → API.

4. Using Supabase in Components

Import and use the client in any component:

import { supabase } from './lib/supabaseClient'

function App() {
  const fetchData = async () => {
    const { data, error } = await supabase
      .from('your_table')
      .select('*')
  }
  // ...
}

Remember to restart your development server after adding environment variables!

Step 7: Cateh Errors & Test Signup / Check Auth in Supabase

Step 8: Route Between Pages: Login & Signup

We will use the React DOM Router component to manage switching pages for login and signup.

Implementing Routing Between Pages in React

I recently implemented page routing in my React application using react-router-dom. Here's how I set it up:

Project Structure

src/
├── Pages/
│   ├── index.js    // Exports all page components
│   ├── Login.jsx
│   └── SignUp.jsx
├── main.jsx       // Wrapped with BrowserRouter
└── App.jsx        // Main application component

Key Implementation Steps

  1. Created three page files in a new Pages folder
  2. Installed router with npm i react-router-dom (v7.8.1)
  3. Wrapped the app with BrowserRouter in main.jsx
  4. Exported components from Pages/index.js for cleaner imports

Code Highlights

main.jsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { BrowserRouter } from 'react-router-dom'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <BrowserRouter><App /></BrowserRouter>
  </StrictMode>
)

Pages/index.js

import Login from './Login'
import SignUp from './SignUp'

export {
    Login,
    SignUp
}

This setup provides a solid foundation for adding more pages and implementing navigation between them. Next steps would be to create the actual routing configuration in App.jsx and build out the page components.

Step 9: Adding Login Page Functionality

I enhanced the Login page by adding a proper form and improving the account creation flow. Here are the key improvements:

Login.jsx Updates

import React from 'react'
import { Link } from 'react-router-dom'

const Login = () => {
  return (
    <div className="login-container">
      <h2>Login</h2>
      <form>
        <input type="email" placeholder="Email" />
        <input type="password" placeholder="Password" />
        <button type="submit">Sign In</button>
      </form>
      <p>
        Don't have an account? <Link to="/signup">Create one</Link>
      </p>
    </div>
  )
}

export default Login

Key Improvements

  • Added complete login form with email and password fields
  • Implemented proper form submission structure
  • Enhanced "Don't have an account?" message with working Link component
  • Added proper routing to SignUp page using react-router-dom

Next Steps

The next enhancements will include form validation, error handling, and connecting to Supabase authentication. I'll also style the form to match the application's design system.

Routing between pages in React — quick walkthrough

Updated just now • React Router • Frontend

You implemented client-side routing and flow from Login → Homepage and set a session token to persist the user's state across refreshes.

  1. Created Homepage.jsx using the rfce / rfce-like snippet to scaffold the component.
  2. Added a <Route path="/homepage"> entry in App.jsx.
  3. Exported Homepage from your pages index with import Homepage from './Homepage' and included it in your grouped export.
  4. Imported the grouped exports in App.jsx with import { SignUp, Login, Homepage } from './pages'.
  5. In Login.jsx added const navigate = useNavigate() and call navigate('/homepage') on successful login.
  6. Stored the session token in sessionStorage and used it to maintain the global session state on refresh.

Testing notes: after logging in, refreshing the browser should keep you on /homepage if the session token is present in session storage.


Comments