mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
docs: update React Native auth quickstart to remove getUser (#42196)
* Move old functions trouble shooting to new guides
* Replace getUser, update, and switch to codeblocks
* Revert "Move old functions trouble shooting to new guides"
This reverts commit 229c581172.
* Prettier
* Add env details
* Fixes
This commit is contained in:
1 parent
dd0f8327ef
commit
587729411d
14 files changed
+8701
-148
No files matched your search
@@ -0,0 +1,36 @@
|
||||
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# Expo
|
||||
.expo/
|
||||
dist/
|
||||
web-build/
|
||||
|
||||
# Native
|
||||
*.orig.*
|
||||
*.jks
|
||||
*.p8
|
||||
*.p12
|
||||
*.key
|
||||
*.mobileprovision
|
||||
|
||||
# Metro
|
||||
.metro-health-check*
|
||||
|
||||
# debug
|
||||
npm-debug.*
|
||||
yarn-debug.*
|
||||
yarn-error.*
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
.env
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'react-native-url-polyfill/auto'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { supabase } from './lib/supabase'
|
||||
import Auth from './components/Auth'
|
||||
import { View, Text } from 'react-native'
|
||||
import { User } from '@supabase/supabase-js'
|
||||
|
||||
export default function App() {
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
supabase.auth.getUser().then(({ data: { user } }) => {
|
||||
setUser(user)
|
||||
})
|
||||
|
||||
supabase.auth.onAuthStateChange((_event, session) => {
|
||||
setUser(session?.user ?? null)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Auth />
|
||||
{user && <Text>{user.id}</Text>}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# Supabase Auth with React Native
|
||||
|
||||
This example demonstrates how to use Supabase Auth with React Native and Expo.
|
||||
|
||||
## Getting started
|
||||
|
||||
### 1. Create a Supabase project
|
||||
|
||||
[Launch a new project](https://supabase.com/dashboard) in the Supabase Dashboard.
|
||||
|
||||
### 2. Configure environment variables
|
||||
|
||||
Create a `.env` file and populate with your Supabase connection variables:
|
||||
|
||||
You can find these in your [Supabase Dashboard](https://supabase.com/dashboard/project/_/settings/api) under Settings > API.
|
||||
|
||||
### 3. Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 4. Start the app
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Follow the instructions in the terminal to open the app on your device or emulator.
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
├── App.tsx # Main app component
|
||||
├── components/
|
||||
│ └── Auth.tsx # Authentication form component
|
||||
├── lib/
|
||||
│ └── supabase.ts # Supabase client configuration
|
||||
├── app.json # Expo configuration
|
||||
├── package.json # Dependencies
|
||||
└── tsconfig.json # TypeScript configuration
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Email/password sign up
|
||||
- Email/password sign in
|
||||
- Session persistence with AsyncStorage
|
||||
- Automatic token refresh
|
||||
|
||||
## Learn more
|
||||
|
||||
- [Supabase Auth Documentation](https://supabase.com/docs/guides/auth)
|
||||
- [React Native Quickstart](https://supabase.com/docs/guides/auth/quickstarts/react-native)
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "Supabase Auth React Native",
|
||||
"slug": "supabase-auth-react-native",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"assetBundlePatterns": ["**/*"],
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"favicon": "./assets/favicon.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,83 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Alert, StyleSheet, View } from 'react-native'
|
||||
import { supabase } from '../lib/supabase'
|
||||
import { Button, Input } from '@rneui/themed'
|
||||
|
||||
export default function Auth() {
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
async function signInWithEmail() {
|
||||
setLoading(true)
|
||||
const { error } = await supabase.auth.signInWithPassword({
|
||||
email: email,
|
||||
password: password,
|
||||
})
|
||||
|
||||
if (error) Alert.alert(error.message)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
async function signUpWithEmail() {
|
||||
setLoading(true)
|
||||
const {
|
||||
data: { session },
|
||||
error,
|
||||
} = await supabase.auth.signUp({
|
||||
email: email,
|
||||
password: password,
|
||||
})
|
||||
|
||||
if (error) Alert.alert(error.message)
|
||||
if (!session) Alert.alert('Please check your inbox for email verification!')
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={[styles.verticallySpaced, styles.mt20]}>
|
||||
<Input
|
||||
label="Email"
|
||||
leftIcon={{ type: 'font-awesome', name: 'envelope' }}
|
||||
onChangeText={(text) => setEmail(text)}
|
||||
value={email}
|
||||
placeholder="email@address.com"
|
||||
autoCapitalize={'none'}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.verticallySpaced}>
|
||||
<Input
|
||||
label="Password"
|
||||
leftIcon={{ type: 'font-awesome', name: 'lock' }}
|
||||
onChangeText={(text) => setPassword(text)}
|
||||
value={password}
|
||||
secureTextEntry={true}
|
||||
placeholder="Password"
|
||||
autoCapitalize={'none'}
|
||||
/>
|
||||
</View>
|
||||
<View style={[styles.verticallySpaced, styles.mt20]}>
|
||||
<Button title="Sign in" disabled={loading} onPress={() => signInWithEmail()} />
|
||||
</View>
|
||||
<View style={styles.verticallySpaced}>
|
||||
<Button title="Sign up" disabled={loading} onPress={() => signUpWithEmail()} />
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginTop: 40,
|
||||
padding: 12,
|
||||
},
|
||||
verticallySpaced: {
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
alignSelf: 'stretch',
|
||||
},
|
||||
mt20: {
|
||||
marginTop: 20,
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,32 @@
|
||||
import { AppState, Platform } from 'react-native'
|
||||
import 'react-native-url-polyfill/auto'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { createClient, processLock } from '@supabase/supabase-js'
|
||||
|
||||
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL!
|
||||
const supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!
|
||||
|
||||
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
|
||||
auth: {
|
||||
...(Platform.OS !== 'web' ? { storage: AsyncStorage } : {}),
|
||||
autoRefreshToken: true,
|
||||
persistSession: true,
|
||||
detectSessionInUrl: false,
|
||||
lock: processLock,
|
||||
},
|
||||
})
|
||||
|
||||
// Tells Supabase Auth to continuously refresh the session automatically
|
||||
// if the app is in the foreground. When this is added, you will continue
|
||||
// to receive `onAuthStateChange` events with the `TOKEN_REFRESHED` or
|
||||
// `SIGNED_OUT` event if the user's session is terminated. This should
|
||||
// only be registered once.
|
||||
if (Platform.OS !== 'web') {
|
||||
AppState.addEventListener('change', (state) => {
|
||||
if (state === 'active') {
|
||||
supabase.auth.startAutoRefresh()
|
||||
} else {
|
||||
supabase.auth.stopAutoRefresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
+8387
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "supabase-auth-react-native",
|
||||
"version": "1.0.0",
|
||||
"main": "node_modules/expo/AppEntry.js",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"web": "expo start --web"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "2.2.0",
|
||||
"@rneui/base": "^5.0.0",
|
||||
"@rneui/themed": "^5.0.0",
|
||||
"@supabase/supabase-js": "^2.93.1",
|
||||
"expo": "~54.0.32",
|
||||
"expo-status-bar": "~3.0.9",
|
||||
"react": "19.1.0",
|
||||
"react-native": "0.81.5",
|
||||
"react-native-safe-area-context": "~5.6.0",
|
||||
"react-native-url-polyfill": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.28.6",
|
||||
"@testing-library/jest-native": "^5.4.3",
|
||||
"@testing-library/react-native": "^13.2.0",
|
||||
"@types/react": "~19.1.0",
|
||||
"typescript": "~5.9.2"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "expo/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user