React Native Examples ​
Complete examples for using Flowfull Clients with React Native (Expo).
Basic Setup ​
App Setup with Provider ​
typescript
// App.tsx
import { PubflowProvider } from '@pubflow/react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import LoginScreen from './screens/LoginScreen';
import HomeScreen from './screens/HomeScreen';
import UsersScreen from './screens/UsersScreen';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<PubflowProvider
config={{
baseUrl: process.env.EXPO_PUBLIC_BACKEND_URL!,
bridgeBasePath: '/bridge',
authBasePath: '/auth',
useSecureStorage: true
}}
>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Users" component={UsersScreen} />
</Stack.Navigator>
</NavigationContainer>
</PubflowProvider>
);
}Authentication ​
Login Screen ​
typescript
// screens/LoginScreen.tsx
import { useState } from 'react';
import { View, TextInput, Button, Text, StyleSheet } from 'react-native';
import { useAuth } from '@pubflow/react-native';
export default function LoginScreen({ navigation }: any) {
const { login, isLoading } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
async function handleLogin() {
setError('');
try {
const result = await login({ email, password });
if (result.success) {
navigation.replace('Home');
} else {
setError(result.error || 'Login failed');
}
} catch (err) {
setError('An error occurred');
}
}
return (
<View style={styles.container}>
<Text style={styles.title}>Login</Text>
<TextInput
style={styles.input}
value={email}
onChangeText={setEmail}
placeholder="Email"
keyboardType="email-address"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
value={password}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry
/>
<Button
title={isLoading ? 'Logging in...' : 'Login'}
onPress={handleLogin}
disabled={isLoading}
/>
{error && <Text style={styles.error}>{error}</Text>}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
textAlign: 'center',
},
input: {
borderWidth: 1,
borderColor: '#ddd',
padding: 10,
marginBottom: 10,
borderRadius: 5,
},
error: {
color: 'red',
marginTop: 10,
textAlign: 'center',
},
});Data Fetching ​
User List with Pull-to-Refresh ​
typescript
// screens/UsersScreen.tsx
import { useState } from 'react';
import { View, FlatList, Text, TouchableOpacity, RefreshControl, StyleSheet } from 'react-native';
import { useBridgeApi, useBridgeQuery } from '@pubflow/react-native';
interface User {
id: string;
name: string;
email: string;
}
export default function UsersScreen() {
const [page, setPage] = useState(1);
const userService = useBridgeApi<User>({ endpoint: 'users' });
const { data, isLoading, error, refetch } = useBridgeQuery(
userService,
'list',
{ page, limit: 20 }
);
if (error) {
return (
<View style={styles.center}>
<Text>Error: {error.message}</Text>
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={data || []}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<TouchableOpacity style={styles.item}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.email}>{item.email}</Text>
</TouchableOpacity>
)}
refreshControl={
<RefreshControl refreshing={isLoading} onRefresh={refetch} />
}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
center: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
item: {
padding: 15,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
name: {
fontSize: 16,
fontWeight: 'bold',
},
email: {
fontSize: 14,
color: '#666',
marginTop: 4,
},
});Protected Screen ​
typescript
// screens/HomeScreen.tsx
import { View, Text, Button, StyleSheet } from 'react-native';
import { useAuth } from '@pubflow/react-native';
export default function HomeScreen({ navigation }: any) {
const { user, logout } = useAuth();
async function handleLogout() {
await logout();
navigation.replace('Login');
}
return (
<View style={styles.container}>
<Text style={styles.title}>Welcome, {user?.name}!</Text>
<Text style={styles.subtitle}>{user?.email}</Text>
<Button title="View Users" onPress={() => navigation.navigate('Users')} />
<Button title="Logout" onPress={handleLogout} color="red" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
textAlign: 'center',
},
subtitle: {
fontSize: 16,
color: '#666',
marginBottom: 30,
textAlign: 'center',
},
});Next Steps ​
- React Examples - Web examples
- Next.js Examples - SSR examples
- Advanced: Offline Support - Offline functionality