To manage state in React you have many different options, but combining Supabase with React Context is a powerful way to keep your app's state in sync with your backend. In this post, I'll show you the code snipped which I have used in my project to manage the state of the user subscription status, but you can adapt it to manage any state in your app.
Setting up your context
We'll create a ProfileContext that can hold any piece of state you want to manage. In this example, we'll track if a user is subscribed, but you can change it to anything else.
Here's the full code:
import {
createContext,
useState,
useMemo,
ReactNode,
useContext,
useCallback,
useEffect,
} from 'react';
import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react';
import toast from 'react-hot-toast';
interface ProfileContextProps {
isSubscribed: boolean;
}
interface ProfileProviderProps {
children: ReactNode;
}
const ProfileContext = createContext<ProfileContextProps>({
isSubscribed: false,
});
const ProfileProvider = ({ children }: ProfileProviderProps) => {
const supabase = useSupabaseClient();
const user = useUser();
const [isSubscribed, setIsSubscribed] = useState<boolean>(false);
const fetchProfile = useCallback(async () => {
try {
let { data, error } = await supabase
.from('profiles')
.select('isSubscribed')
.eq('id', user?.id)
.single();
if (error) throw error;
if (data) {
setIsSubscribed(data.isSubscribed);
}
} catch (error) {
toast('An error occurred. Please try again later.');
console.log(error);
}
}, [supabase, user]);
useEffect(() => {
if (user) {
fetchProfile();
}
}, [fetchProfile, user]);
return (
<ProfileContext.Provider
value={useMemo(
()=> ({
isSubscribed,
}),
[isSubscribed]
)}
>
{children}
</ProfileContext.Provider>
);
};
const useProfileContext = () => {
return useContext(ProfileContext);
};
export { useProfileContext, ProfileContext, ProfileProvider };
So what happens here? Let's break it down:
- We create a
ProfileContextwith a default value forisSubscribed. - Profile provider component:
- We use
useStateto manageisSubscribed. fetchProfileuses Supabase to get the subscription status from the profiles table.useEffectcallsfetchProfilewhenever the user changes.useMemoensures the context value updates only whenisSubscribedchanges.useProfileContextmakes it easy to access the context in your components.
Note #1: This code assumes you have a
profilestable in your Supabase database with a columnisSubscribed. You can adjust it to fit your schema.
Note #2:
react-hot-toastis used for displaying error messages. You can replace it with any other toast library or error handling mechanism.
How to use it
Wrap your components with ProfileProvider and use the useProfileContext hook to get the context values.
import { ProfileProvider, useProfileContext } from './profileContext';
const App = () => {
return (
<ProfileProvider>
<MainComponent />
</ProfileProvider>
);
};
const MainComponent = () => {
const { isSubscribed } = useProfileContext();
return (
<div>
{isSubscribed ? <PremiumContent /> : <StandardContent />}
</div>
);
};
Combining React Context with Supabase is a great way to manage state in your app. This example shows how to keep your app's state in sync with your backend easily. Whether it's subscription status or any other piece of state, this approach helps you maintain clean and efficient code.
Got questions or comments? Feel free to leave them below.