avatarKhoa Pham

Summary

The provided context outlines the process of integrating Supabase authentication with a React application using React Context.

Abstract

The web content details a method for implementing Supabase authentication within a React application. It begins by demonstrating how to expose Supabase with the createClient function and provides code snippets for creating a Supabase client using environment variables. The article then proceeds to explain how to manage authentication state within a React application by wrapping the auth state in a custom React Context called AuthProvider. This includes setting up state hooks for session and user data, using the onAuthStateChange listener to update these states in real-time, and providing a mechanism to retrieve initial authentication state with getSession. The AuthProvider component is designed to be a higher-order component that encapsulates authentication logic, making it easy to pass down authentication state and functions to child components throughout the application. Finally, the content includes a utility hook useAuth for accessing the authentication context, and the AuthProvider is exported as the default for use in the application.

Opinions

  • The use of Supabase for authentication is presented as a straightforward solution, particularly with the integration of React Context for state management.
  • Employing environment variables for Supabase credentials is recommended for security best practices.
  • Real-time authentication state management is emphasized as important, with the onAuthStateChange listener being a key component for maintaining up-to-date user session information.
  • The pattern of using React Context for global state management, such as authentication, is implied to be a clean and efficient approach for React applications.
  • Encapsulating authentication logic within an AuthProvider simplifies the consumption of authentication data and functions across

How to use Supabase auth with React Context

Expose supabase with createClient

useSupabase.ts

import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.SUPABASE_URL
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl!, supabaseAnonKey!)
export const signIn = async () => {
    await supabase.auth.signInWithOAuth({
        provider: 'twitter'
    });
}
export const signOut = async () => {
    await supabase.auth.signOut();
}

{ await supabase.auth.signInWithOAuth({ provider: ‘twitter’ }); } export const signOut = async () => { await supabase.auth.signOut(); }” tabindex=”0" role=”button” style=”box-sizing: border-box; position: relative; display: inline-block; padding: 0px !important; font-size: 14px; font-weight: var( — base-text-weight-medium, 500); line-height: 20px; white-space: nowrap; vertical-align: middle; cursor: pointer; user-select: none; border-width: 1px; border-style: solid; border-color: var( — button-default-borderColor-rest, var( — color-btn-border)); border-image: initial; border-radius: 6px; appearance: none; color: var( — button-default-fgColor-rest, var( — color-btn-text)); background-color: var( — button-default-bgColor-rest, var( — color-btn-bg)); box-shadow: var( — button-default-shadow-resting, var( — color-btn-shadow)),var( — button-default-shadow-inset, var( — color-btn-inset-shadow)); transition: color 80ms cubic-bezier(0.33, 1, 0.68, 1) 0s, background-color, box-shadow, border-color; margin: var( — base-size-8, 8px) !important;”>

Wrap auth state in React Context

AuthProvider.tsx

import React, { useContext, createContext, useState, useEffect } from 'react'
import { Session, User } from '@supabase/supabase-js'
import { supabase } from './useSupabase'
interface AuthProviderProps {
    children: React.ReactNode
}
type AuthContextType = {
    session: Session | null,
    user: User | null
}
const AuthContext = createContext<AuthContextType>({
    session: null,
    user: null
})
const AuthProvider = (props: AuthProviderProps) => {
    const [user, setUser] = useState<User | null>(null)
    const [session, setSession] = useState<Session | null>(null)
    const [loading, setLoading] = useState<boolean>(true)
    useEffect(() => {
        const { data: listener } = supabase.auth.onAuthStateChange((_event, session) => {
            setSession(session)
            setUser(session?.user || null)
            setLoading(false)
        })
        const setData = async () => {
            const { data : {session}, error } = await supabase.auth.getSession()
            if (error) {
                throw error
            }
            setSession(session)
            setUser(session?.user || null)
            setLoading(false)
        }
        setData()
        
        return () => {
            listener?.subscription.unsubscribe()    
        }
    }, [])
    const value = {
        session,
        user
    }
    return (
        <AuthContext.Provider value={value}>
            {props.children}
        </AuthContext.Provider>
    )
}
export const useAuth = () => {
    return useContext(AuthContext)
}
export default AuthProvider
React
Supabase
Context
Auth
Typescript
Recommended from ReadMedium