Expo Setup
newSet up refirebase in an Expo (Expo Router) project.
Install
terminal
# Install refirebase
npx expo install refirebase
# Install native Google Sign-In (optional)
npx expo install @react-native-google-signin/google-signin
# Install Expo ImagePicker (for file uploads)
npx expo install expo-image-pickerEnvironment variables
Expo uses the EXPO_PUBLIC_ prefix for client-accessible variables. Pass them explicitly to the constructor since Refirebase does not read EXPO_PUBLIC_* automatically.
.env
# .env
EXPO_PUBLIC_FIREBASE_API_KEY=AIza...
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
EXPO_PUBLIC_FIREBASE_PROJECT_ID=your-project
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=123456789
EXPO_PUBLIC_FIREBASE_APP_ID=1:123456789:web:abc
EXPO_PUBLIC_FIREBASE_DATABASE_URL=https://your-project-rtdb.firebaseio.comInitialize
app/firebase.ts
// app/firebase.ts
import { Refirebase } from 'refirebase';
export const firebase = new Refirebase({
apiKey: process.env.EXPO_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.EXPO_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.EXPO_PUBLIC_FIREBASE_APP_ID,
databaseURL: process.env.EXPO_PUBLIC_FIREBASE_DATABASE_URL,
});Provider
app/_layout.tsx
// app/_layout.tsx (Expo Router)
import { Stack } from 'expo-router';
import { RefirebaseProvider } from 'refirebase/react';
import { firebase } from './firebase';
export default function RootLayout() {
return (
<RefirebaseProvider instance={firebase}>
<Stack />
</RefirebaseProvider>
);
}Screen example
app/(tabs)/profile.tsx
// app/(tabs)/profile.tsx
import { useAuth, useCollection } from 'refirebase/react';
import { GoogleSignin } from '@react-native-google-signin/google-signin';
GoogleSignin.configure({ webClientId: 'YOUR_WEB_CLIENT_ID' });
export default function ProfileScreen() {
const { user, loading, signInWithGoogle, signOut } = useAuth();
const { data: posts } = useCollection('posts');
const handleGoogleSignIn = async () => {
const { idToken } = await GoogleSignin.signIn();
await signInWithGoogle({ idToken });
};
if (loading) return <ActivityIndicator />;
if (!user) {
return <Button title="Sign in with Google" onPress={handleGoogleSignIn} />;
}
return (
<View>
<Text>Hello, {user.displayName}</Text>
<FlatList
data={posts}
renderItem={({ item }) => <Text>{item.title}</Text>}
keyExtractor={(item) => item.id}
/>
<Button title="Sign out" onPress={signOut} />
</View>
);
}File upload
Use uriToBlob to convert Expo ImagePicker URIs to Blobs, then upload with progress using useUploadTask.
AvatarPicker.tsx
import { uriToBlob } from 'refirebase';
import { useUploadTask } from 'refirebase/react';
import * as ImagePicker from 'expo-image-picker';
export function AvatarPicker() {
const { upload, progress, state } = useUploadTask();
const pick = async () => {
const result = await ImagePicker.launchImageLibraryAsync({ quality: 0.8 });
if (!result.canceled) {
const blob = await uriToBlob(result.assets[0].uri);
await upload('avatars/me.jpg', blob, { downloadUrl: true });
}
};
return (
<View>
<Button title="Pick photo" onPress={pick} />
{state === 'running' && <Text>Uploading {progress}%...</Text>}
</View>
);
}