React Native (Expo) - Auth session not persisting after moving to supabase.js v2
Hi there, I've recently made the jump to Supabase.js v2 but I'm having an issue where every time I make a change in my development environment it seems to sign me out? It wasn't doing this before and it's incredibly frustrating having to go through auth flow every time I make a 1-line-of-code change
Would anyone be able to take a look at my Auth flow below and tell me what's broken or has changed?
1 Reply
App.js
Auth.js
supabase.js
authHandler.js
The version of react-native-elements used in the Expo quickstart guide is deprecated btw
https://reactnativeelements.com/docs/installation#using-expo
This contains the new packages/system
Alright, it seems to have decided to work -- going to close?
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import * as NavigationBar from "expo-navigation-bar";
import { StatusBar } from "expo-status-bar";
import { NavigationContainer } from "@react-navigation/native";
import { useEffect, useState } from "react";
import { RecoilRoot } from "recoil";
import Home from "./views/Home";
import Auth from "./views/Auth";
import { supabase } from "./state/supabase";
import BoardView from "./views/BoardView";
import BoardEditor from "./views/BoardEditor.js";
const Stack = createNativeStackNavigator();
export default function App() {
const [session, setSession] = useState(null);
NavigationBar.setVisibilityAsync("hidden");
async function authHandler() {
let { data } = await supabase.auth.getSession();
setSession(data);
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
}
useEffect(() => {
authHandler();
}, []);
return (
<RecoilRoot>
<StatusBar hidden={true} />
{session && session.user ? (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Board" component={BoardView} />
<Stack.Screen
name="BoardEditor"
component={BoardEditor}
/>
</Stack.Navigator>
</NavigationContainer>
) : (
<Auth />
)}
</RecoilRoot>
);
}
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import * as NavigationBar from "expo-navigation-bar";
import { StatusBar } from "expo-status-bar";
import { NavigationContainer } from "@react-navigation/native";
import { useEffect, useState } from "react";
import { RecoilRoot } from "recoil";
import Home from "./views/Home";
import Auth from "./views/Auth";
import { supabase } from "./state/supabase";
import BoardView from "./views/BoardView";
import BoardEditor from "./views/BoardEditor.js";
const Stack = createNativeStackNavigator();
export default function App() {
const [session, setSession] = useState(null);
NavigationBar.setVisibilityAsync("hidden");
async function authHandler() {
let { data } = await supabase.auth.getSession();
setSession(data);
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
}
useEffect(() => {
authHandler();
}, []);
return (
<RecoilRoot>
<StatusBar hidden={true} />
{session && session.user ? (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Board" component={BoardView} />
<Stack.Screen
name="BoardEditor"
component={BoardEditor}
/>
</Stack.Navigator>
</NavigationContainer>
) : (
<Auth />
)}
</RecoilRoot>
);
}
import { useState } from "react";
import {
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import { signIn, signUp } from "../state/handlers/authHandler";
export default function Auth() {
const [email, setEmaiil] = useState("");
const [password, setPassword] = useState("");
return (
<View style={styles.container}>
<View styles={styles.topBar}>
<Text style={styles.topBarText}>Authentication</Text>
</View>
<View style={styles.fields}>
<View style={styles.field}>
<Text style={styles.fieldText}>Email</Text>
<TextInput
style={styles.fieldInput}
value={email}
onChangeText={setEmaiil}
/>
</View>
<View style={styles.field}>
<Text style={styles.fieldText}>Password</Text>
<TextInput
style={styles.fieldInput}
secureTextEntry={true}
value={password}
onChangeText={setPassword}
/>
</View>
<TouchableOpacity
style={[styles.button, styles.buttonActive]}
onPress={() => {
signUp(email, password);
}}
>
<Text style={styles.buttonActiveText}>Sign Up</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => {
signIn(email, password);
}}
>
<Text style={styles.buttonText}>Sign In</Text>
</TouchableOpacity>
</View>
</View>
);
}
import { useState } from "react";
import {
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import { signIn, signUp } from "../state/handlers/authHandler";
export default function Auth() {
const [email, setEmaiil] = useState("");
const [password, setPassword] = useState("");
return (
<View style={styles.container}>
<View styles={styles.topBar}>
<Text style={styles.topBarText}>Authentication</Text>
</View>
<View style={styles.fields}>
<View style={styles.field}>
<Text style={styles.fieldText}>Email</Text>
<TextInput
style={styles.fieldInput}
value={email}
onChangeText={setEmaiil}
/>
</View>
<View style={styles.field}>
<Text style={styles.fieldText}>Password</Text>
<TextInput
style={styles.fieldInput}
secureTextEntry={true}
value={password}
onChangeText={setPassword}
/>
</View>
<TouchableOpacity
style={[styles.button, styles.buttonActive]}
onPress={() => {
signUp(email, password);
}}
>
<Text style={styles.buttonActiveText}>Sign Up</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => {
signIn(email, password);
}}
>
<Text style={styles.buttonText}>Sign In</Text>
</TouchableOpacity>
</View>
</View>
);
}
import AsyncStorage from "@react-native-async-storage/async-storage";
import { createClient } from "@supabase/supabase-js";
import { setupURLPolyfill } from "react-native-url-polyfill";
import appjson from "../app.json";
setupURLPolyfill();
export const supabase = createClient(
appjson.supabase.url,
appjson.supabase.anon_key,
{
auth: {
storage: AsyncStorage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
},
}
);
import AsyncStorage from "@react-native-async-storage/async-storage";
import { createClient } from "@supabase/supabase-js";
import { setupURLPolyfill } from "react-native-url-polyfill";
import appjson from "../app.json";
setupURLPolyfill();
export const supabase = createClient(
appjson.supabase.url,
appjson.supabase.anon_key,
{
auth: {
storage: AsyncStorage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
},
}
);
import { Alert } from "react-native";
import { supabase } from "../supabase";
let signIn = async (email, password) => {
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) Alert.alert(error.message);
return error;
};
let signUp = async (email, password) => {
const { error } = await supabase.auth.signUp({
email,
password,
});
if (error) Alert.alert(error.message);
return error;
};
export { signIn, signUp };
import { Alert } from "react-native";
import { supabase } from "../supabase";
let signIn = async (email, password) => {
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) Alert.alert(error.message);
return error;
};
let signUp = async (email, password) => {
const { error } = await supabase.auth.signUp({
email,
password,
});
if (error) Alert.alert(error.message);
return error;
};
export { signIn, signUp };