I'm building a mobile app with React Native (Expo) and using Supabase for authentication and user profiles.
This is my profiles table
create table public.profiles (
id uuid primary key references auth.users(id),
full_name text,
birth_date date,
gender text,
city text,
postal_code text,
leisure_preferences text[],
notify_events boolean default false,
notify_recommendations boolean default false,
notify_news boolean default false,
onboarding_completed boolean default false
);
My RLS policies:
-- Insert
alter policy "Enable insert for users based on user_id"
on public.profiles
to public
with check (auth.uid() = id);
-- Update
alter policy "Enable update for users"
on public.profiles
to public
using (id = auth.uid())
with check (auth.uid() = id);
-- Select
alter policy "select profile"
on public.profiles
to public
using (auth.uid() = id);
In my OnboardingScreen, I try to save the user profile when pressing Save:
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
const user = session?.user;
const { data, error } = await supabase
.from('profiles')
.upsert([{
id: user.id,
full_name: nombre,
birth_date: fechaNacimiento,
gender: genero,
city: ciudad,
postal_code: codigoPostal,
leisure_preferences: preferencias,
notify_events: alertasEventos,
notify_recommendations: recomendaciones,
notify_news: novedades,
onboarding_completed: true,
}], { onConflict: 'id' })
.select();
console.log('Result:', { data, error });
My App.tsx
const [session, setSession] = useState<any>(null);
const [loading, setLoading] = useState<boolean>(true);
const [onboardingCompleted, setOnboardingCompleted] = useState<boolean>(false);
useEffect(() => {
const getSession = async () => {
try {
const { data, error } = await supabase.auth.getSession();
if (error) throw error;
setSession(data?.session ?? null);
if (data?.session?.user) {
await checkOnboardingStatus(data.session.user.id);
}
} catch (error) {
console.error('Error al obtener la sesión:', error);
} finally {
setLoading(false);
}
};
const checkOnboardingStatus = async (userId: string) => {
try {
const { data, error } = await supabase
.from('profiles')
.select('onboarding_completed')
.eq('id', userId)
.single();
if (error) throw error;
console.log('Estado de onboarding obtenido:', data?.onboarding_completed);
setOnboardingCompleted(data?.onboarding_completed ?? false);
} catch (error) {
console.error('Error al verificar el estado de Onboarding:', error);
}
};
getSession();
const { data: authListener } = supabase.auth.onAuthStateChange(async (_event: any, currentSession: any) => {
setSession(currentSession);
if (currentSession?.user) {
await checkOnboardingStatus(currentSession.user.id);
}
});
return () => {
authListener?.subscription?.unsubscribe(); // Asegúrate de acceder a `subscription` antes de llamar a `unsubscribe`
};
}, []);
return (
<SafeAreaProvider>
<View style={{ flex: 1, backgroundColor: '#1B1A1A' }}>
<EventProvider>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false, animation: 'slide_from_right' }}>
{!session ? (
<Stack.Screen name="Login" component={LoginScreen} />
) : onboardingCompleted ? (
<>
<Stack.Screen name="MainApp" component={MainAppTabs} />
<Stack.Screen name="EventDetailsScreen" component={EventDetailsScreen} />
</>
) : (
<Stack.Screen name="Onboarding">
{props => (
<OnboardingScreen
{...props}
setOnboardingCompleted={setOnboardingCompleted}
/>
)}
</Stack.Screen>
)}
</Stack.Navigator>
</NavigationContainer>
</EventProvider>
</View>
</SafeAreaProvider>
);
}
The button press works (handleSave runs, I see logs) But the upsert never seems to update the row In Supabase, the onboarding_completed field stays false. Because of that, my App.tsx logic never switches to MainApp
lang-sql