Gathering detailed insights and metrics for akshay-khapare-react-native-firebase-hooks
Gathering detailed insights and metrics for akshay-khapare-react-native-firebase-hooks
Gathering detailed insights and metrics for akshay-khapare-react-native-firebase-hooks
Gathering detailed insights and metrics for akshay-khapare-react-native-firebase-hooks
@akshay-khapare/rn-multi-firebase-config
Production-ready utility package for managing multiple Firebase projects within a single React Native application with optimized hooks, comprehensive error handling, and full TypeScript support
akshay-khapare-expo-firebase-hooks
Production-ready Firebase hooks for Expo React Native applications with comprehensive error handling
npm install akshay-khapare-react-native-firebase-hooks
Typescript
Module System
Min. Node Version
Node Version
NPM Version
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
1 Contributors
Updated on Jun 21, 2025
Latest Version
1.0.3
Package Id
akshay-khapare-react-native-firebase-hooks@1.0.3
Unpacked Size
314.39 kB
Size
46.30 kB
File Count
72
NPM Version
11.4.0
Node Version
22.11.0
Published on
Jul 02, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
6
20
The most comprehensive, production-ready React Native Firebase hooks library with advanced error handling, zero crashes, and complete type safety.
1npm install akshay-khapare-react-native-firebase-hooks
1npm install @react-native-firebase/app @react-native-firebase/firestore @react-native-firebase/auth @react-native-firebase/storage
📱 React Native Components: All code examples use React Native components (
View
,Text
,TouchableOpacity
,FlatList
,TextInput
, etc.). Import these from'react-native'
in your components. For data persistence, examples useAsyncStorage
from@react-native-async-storage/async-storage
.
1import React, { useState, useEffect } from 'react'; 2import { View, Text, TouchableOpacity } from 'react-native'; 3import { 4 initializeFirebase, 5 useFirestoreSet, 6 ERROR_CODES, 7} from 'akshay-khapare-react-native-firebase-hooks'; 8 9// Initialize Firebase 10await initializeFirebase({ 11 projectName: '[DEFAULT]', 12 config: firebaseConfig, 13 onError: (error) => console.error('Init failed:', error.code), 14}); 15 16// Use hooks with error handling - No try/catch needed! 17const { setData } = useFirestoreSet(); 18 19const createUser = async (userData) => { 20 const docId = await setData({ 21 collection: 'users', 22 doc: 'user123', 23 data: userData, 24 onError: (error) => { 25 // Handle specific errors with error codes 26 switch (error.code) { 27 case ERROR_CODES.VALIDATION_DATA_EMPTY: 28 showToast('Please fill in user data'); 29 break; 30 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 31 showToast('Permission denied. Please login.'); 32 break; 33 default: 34 showToast('Failed to create user'); 35 } 36 }, 37 }); 38 39 if (docId) { 40 showToast('User created successfully!'); 41 } 42};
1import { 2 initializeFirebase, 3 configureFirestore, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const setupFirebase = async () => { 7 await initializeFirebase({ 8 projectName: '[DEFAULT]', 9 config: { 10 apiKey: 'your-api-key', 11 authDomain: 'your-project.firebaseapp.com', 12 projectId: 'your-project-id', 13 storageBucket: 'your-project.appspot.com', 14 messagingSenderId: '123456789', 15 appId: '1:123456789:web:abcdef', 16 }, 17 onError: (error) => { 18 logError('Firebase init failed', error); 19 }, 20 }); 21 22 await configureFirestore({ 23 projectName: '[DEFAULT]', 24 persistence: true, 25 cacheSizeBytes: -1, // Unlimited cache 26 }); 27};
1import { initializeMultipleFirebaseProjects } from 'akshay-khapare-react-native-firebase-hooks'; 2 3await initializeMultipleFirebaseProjects({ 4 configs: [ 5 { name: 'production', config: prodConfig }, 6 { name: 'analytics', config: analyticsConfig }, 7 ], 8 onError: (error) => console.error('Multi-project setup failed:', error), 9});
The library also exports Firebase service instances for direct access:
1import { 2 auth, 3 firestore, 4 storage, 5} from 'akshay-khapare-react-native-firebase-hooks'; 6 7// Direct access to Firebase services 8const AuthService = () => { 9 const signInUser = async () => { 10 try { 11 await auth().signInWithEmailAndPassword(email, password); 12 } catch (error) { 13 console.error('Auth error:', error); 14 } 15 }; 16}; 17 18const DirectFirestoreAccess = () => { 19 const directOperation = async () => { 20 // Direct Firestore access for complex operations 21 const batch = firestore().batch(); 22 const userRef = firestore().collection('users').doc('user123'); 23 24 batch.set(userRef, { name: 'John' }); 25 await batch.commit(); 26 }; 27}; 28 29const StorageOperations = () => { 30 const uploadFile = async (file) => { 31 const ref = storage().ref(`uploads/${file.name}`); 32 await ref.putFile(file); 33 return ref.getDownloadURL(); 34 }; 35};
1import { 2 useFirestoreSet, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const CreateUser = () => { 7 const { setData } = useFirestoreSet(); 8 9 const createUser = async () => { 10 const docId = await setData({ 11 collection: 'users', 12 doc: 'user123', // or use firestore().collection('users').doc().id for auto-ID 13 data: { 14 name: 'John Doe', 15 email: 'john@example.com', 16 status: 'active', 17 }, 18 merge: false, // true to merge with existing data 19 addTimestamp: true, // Adds updatedAt server timestamp 20 onError: (error) => handleSetError(error), 21 }); 22 23 if (docId) { 24 console.log('User created with ID:', docId); 25 } 26 }; 27 28 const handleSetError = (error) => { 29 switch (error.code) { 30 case ERROR_CODES.VALIDATION_COLLECTION_EMPTY: 31 showToast('Collection name is required'); 32 break; 33 case ERROR_CODES.VALIDATION_DOCUMENT_EMPTY: 34 showToast('Document ID is required'); 35 break; 36 case ERROR_CODES.VALIDATION_DATA_INVALID: 37 showToast('Invalid data format'); 38 break; 39 case ERROR_CODES.VALIDATION_DATA_EMPTY: 40 showToast('Data cannot be empty'); 41 break; 42 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 43 showToast('Permission denied'); 44 break; 45 case ERROR_CODES.OPERATION_SET_FAILED: 46 showToast('Failed to save data'); 47 break; 48 default: 49 showToast('An error occurred'); 50 } 51 }; 52};
1const { setData } = useFirestoreSet(); 2 3// Create user in specific project 4await setData({ 5 collection: 'users', 6 doc: userId, 7 data: userData, 8 firebaseProject: 'analytics', // Use specific project 9 merge: true, 10 addTimestamp: true, 11 onError: (error) => { 12 logToAnalytics('user_creation_failed', { 13 errorCode: error.code, 14 errorNumber: error.codeNumber, 15 category: error.category, 16 }); 17 }, 18});
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
doc | string | ✅ | Document ID |
data | Record<string, unknown> | ✅ | Document data |
merge | boolean | ❌ | Merge with existing data (default: false) |
addTimestamp | boolean | ❌ | Add updatedAt timestamp (default: false) |
firebaseProject | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
1import { useFirestoreGet, ERROR_CODES } from 'akshay-khapare-react-native-firebase-hooks'; 2 3const UserProfile = ({ userId }) => { 4 const { getData } = useFirestoreGet(); 5 const [user, setUser] = useState(null); 6 const [loading, setLoading] = useState(false); 7 8 const fetchUser = async (source = 'default') => { 9 setLoading(true); 10 11 const result = await getData({ 12 collection: 'users', 13 doc: userId, 14 source, // 'default' | 'server' | 'cache' 15 onError: (error) => handleGetError(error) 16 }); 17 18 setLoading(false); 19 20 if (result) { 21 setUser({ 22 id: result.id, 23 ...result.data, 24 isFromCache: result.fromCache, 25 hasPendingWrites: result.hasPendingWrites 26 }); 27 } 28 }; 29 30 const handleGetError = (error) => { 31 switch (error.code) { 32 case ERROR_CODES.VALIDATION_COLLECTION_EMPTY: 33 case ERROR_CODES.VALIDATION_DOCUMENT_EMPTY: 34 showToast('Invalid document reference'); 35 break; 36 case ERROR_CODES.VALIDATION_SOURCE_INVALID: 37 showToast('Invalid data source specified'); 38 break; 39 case ERROR_CODES.FIREBASE_DOCUMENT_NOT_FOUND: 40 showToast('User not found'); 41 break; 42 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 43 showToast('Access denied'); 44 break; 45 case ERROR_CODES.OPERATION_GET_FAILED: 46 showToast('Failed to load user data'); 47 break; 48 default: 49 showToast('An error occurred while loading'); 50 } 51 }; 52 53 return ( 54 <View> 55 <TouchableOpacity onPress={() => fetchUser('cache')}> 56 <Text>Load from Cache</Text> 57 </TouchableOpacity> 58 <TouchableOpacity onPress={() => fetchUser('server')}> 59 <Text>Refresh from Server</Text> 60 </TouchableOpacity> 61 {loading && <LoadingSpinner />} 62 {user && <UserDisplay user={user} />} 63 </View> 64 ); 65};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
doc | string | ✅ | Document ID |
source | 'default' | 'server' | 'cache' | ❌ | Data source (default: 'default') |
firebaseProjectName | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
1interface DocumentResponse<T> { 2 id: string; // Document ID 3 exists: boolean; // Whether document exists 4 data: T | null; // Document data 5 fromCache: boolean; // Data from cache 6 hasPendingWrites: boolean; // Has pending writes 7}
1import { 2 useFirestoreUpdate, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const UpdateUserProfile = () => { 7 const { updateData } = useFirestoreUpdate(); 8 9 const updateUserStatus = async (userId, status) => { 10 const result = await updateData({ 11 collection: 'users', 12 doc: userId, 13 data: { 14 status, 15 lastModified: new Date(), 16 }, 17 addTimestamp: true, // Adds updatedAt server timestamp 18 onError: (error) => handleUpdateError(error, userId), 19 }); 20 21 if (result) { 22 showToast('User status updated successfully'); 23 } 24 }; 25 26 const handleUpdateError = (error, userId) => { 27 switch (error.code) { 28 case ERROR_CODES.VALIDATION_DATA_EMPTY: 29 showToast('No data provided for update'); 30 break; 31 case ERROR_CODES.FIREBASE_DOCUMENT_NOT_FOUND: 32 showToast('User not found'); 33 break; 34 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 35 showToast('Permission denied to update user'); 36 break; 37 case ERROR_CODES.OPERATION_UPDATE_FAILED: 38 showToast('Failed to update user'); 39 logError('User update failed', { userId, error }); 40 break; 41 default: 42 showToast('Update failed'); 43 } 44 }; 45};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
doc | string | ✅ | Document ID |
data | Partial<T> | ✅ | Update data |
addTimestamp | boolean | ❌ | Add updatedAt timestamp |
firebaseProject | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
1import { 2 useFirestoreGetQuery, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const ProductsList = () => { 7 const { getQuery } = useFirestoreGetQuery(); 8 const [products, setProducts] = useState([]); 9 const [lastDoc, setLastDoc] = useState(null); 10 const [loading, setLoading] = useState(false); 11 12 const loadProducts = async (loadMore = false) => { 13 setLoading(true); 14 15 const result = await getQuery( 16 { 17 collection: 'products', 18 where: [ 19 ['status', '==', 'published'], 20 ['price', '>', 0], 21 ['category', 'in', ['electronics', 'books']], 22 ], 23 orderBy: [ 24 ['featured', 'desc'], 25 ['createdAt', 'desc'], 26 ], 27 limit: 20, 28 ...(loadMore && lastDoc ? { startAfter: lastDoc } : {}), 29 onError: (error) => handleQueryError(error), 30 }, 31 { 32 source: 'default', // Query options 33 } 34 ); 35 36 setLoading(false); 37 38 if (result) { 39 const newProducts = result.map((doc) => ({ 40 id: doc.id, 41 ...doc.data, 42 isFromCache: doc.fromCache, 43 })); 44 45 setProducts((prev) => 46 loadMore ? [...prev, ...newProducts] : newProducts 47 ); 48 if (result.length > 0) { 49 setLastDoc(result[result.length - 1]); 50 } 51 } 52 }; 53 54 const handleQueryError = (error) => { 55 switch (error.code) { 56 case ERROR_CODES.VALIDATION_WHERE_CLAUSE_INVALID: 57 showToast('Invalid search criteria'); 58 break; 59 case ERROR_CODES.VALIDATION_ORDER_BY_INVALID: 60 showToast('Invalid sorting criteria'); 61 break; 62 case ERROR_CODES.VALIDATION_LIMIT_INVALID: 63 showToast('Invalid page size'); 64 break; 65 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 66 showToast('Access denied to products'); 67 break; 68 case ERROR_CODES.OPERATION_QUERY_FAILED: 69 showToast('Failed to load products'); 70 break; 71 default: 72 showToast('Search failed'); 73 } 74 }; 75};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
where | [string, WhereFilterOp, unknown][] | ❌ | Where conditions |
orderBy | [string, 'asc' | 'desc'][] | ❌ | Sort conditions |
limit | number | ❌ | Results limit (positive integer) |
startAt | unknown | ❌ | Start cursor value |
startAfter | unknown | ❌ | Start after cursor value |
endAt | unknown | ❌ | End cursor value |
endBefore | unknown | ❌ | End before cursor value |
firebaseProjectName | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
Parameter | Type | Required | Description |
---|---|---|---|
source | 'default' | 'server' | 'cache' | ❌ | Query data source |
1interface QueryResult<T> { 2 id: string; // Document ID 3 data: T; // Document data 4 fromCache: boolean; // Data retrieved from cache 5 hasPendingWrites: boolean; // Document has pending writes 6}
1const PaginatedQuery = () => { 2 const { getQuery } = useFirestoreGetQuery(); 3 const [lastVisible, setLastVisible] = useState(null); 4 const [firstVisible, setFirstVisible] = useState(null); 5 6 // Forward pagination 7 const loadNext = async () => { 8 const result = await getQuery({ 9 collection: 'posts', 10 orderBy: [['createdAt', 'desc']], 11 limit: 10, 12 startAfter: lastVisible, // Start after last document 13 onError: (error) => { 14 switch (error.code) { 15 case ERROR_CODES.VALIDATION_LIMIT_INVALID: 16 showToast('Invalid page size specified'); 17 break; 18 default: 19 showToast('Failed to load next page'); 20 } 21 }, 22 }); 23 24 if (result && result.length > 0) { 25 setLastVisible(result[result.length - 1]); 26 if (!firstVisible) setFirstVisible(result[0]); 27 } 28 }; 29 30 // Backward pagination 31 const loadPrevious = async () => { 32 const result = await getQuery({ 33 collection: 'posts', 34 orderBy: [['createdAt', 'desc']], 35 limit: 10, 36 endBefore: firstVisible, // End before first document 37 onError: (error) => handleQueryError(error), 38 }); 39 40 if (result && result.length > 0) { 41 setFirstVisible(result[0]); 42 setLastVisible(result[result.length - 1]); 43 } 44 }; 45};
1import { 2 useCollectionListener, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const ChatMessages = ({ chatId }) => { 7 const { listenToCollection } = useCollectionListener(); 8 const [messages, setMessages] = useState([]); 9 10 useEffect(() => { 11 const unsubscribe = listenToCollection({ 12 collection: 'messages', 13 where: [['chatId', '==', chatId]], 14 orderBy: [['timestamp', 'desc']], 15 limit: 50, 16 includeMetadataChanges: true, 17 18 onData: (messageData) => { 19 const newMessages = messageData.map((doc) => ({ 20 id: doc.id, 21 ...doc.data, 22 isPending: doc.hasPendingWrites, 23 isFromCache: doc.fromCache, 24 })); 25 setMessages(newMessages); 26 }, 27 28 onError: (error) => handleListenerError(error), 29 }); 30 31 return () => unsubscribe(); 32 }, [chatId]); 33 34 const handleListenerError = (error) => { 35 switch (error.code) { 36 case ERROR_CODES.VALIDATION_CALLBACK_MISSING: 37 console.error('onData callback is required'); 38 break; 39 case ERROR_CODES.LISTENER_SETUP_FAILED: 40 showToast('Failed to connect to chat'); 41 break; 42 case ERROR_CODES.LISTENER_SNAPSHOT_ERROR: 43 showToast('Connection interrupted'); 44 break; 45 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 46 showToast('Access denied to chat'); 47 break; 48 default: 49 showToast('Chat connection error'); 50 } 51 }; 52};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
onData | (data: DocumentData<T>[]) => void | ✅ | Data callback |
onError | (error: FirebaseHookError) => void | ✅ | Error handler (required) |
where | [string, WhereFilterOp, unknown][] | ❌ | Where conditions |
orderBy | [string, 'asc' | 'desc'][] | ❌ | Sort conditions |
limit | number | ❌ | Results limit |
includeMetadataChanges | boolean | ❌ | Include metadata changes |
firebaseProject | string | ❌ | Firebase project name |
1import { 2 useDocumentListener, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const UserProfileLive = ({ userId }) => { 7 const { listenToDocument } = useDocumentListener(); 8 const [user, setUser] = useState(null); 9 10 useEffect(() => { 11 const unsubscribe = listenToDocument({ 12 collection: 'users', 13 doc: userId, 14 includeMetadataChanges: true, 15 16 onData: (docData) => { 17 if (docData.exists) { 18 setUser({ 19 id: docData.id, 20 ...docData.data, 21 isOnline: !docData.fromCache, 22 hasUnsavedChanges: docData.hasPendingWrites, 23 }); 24 } else { 25 setUser(null); 26 } 27 }, 28 29 onError: (error) => handleDocListenerError(error, userId), 30 }); 31 32 return () => unsubscribe(); 33 }, [userId]); 34 35 const handleDocListenerError = (error, userId) => { 36 switch (error.code) { 37 case ERROR_CODES.VALIDATION_DOCUMENT_EMPTY: 38 console.error('User ID is required'); 39 break; 40 case ERROR_CODES.LISTENER_SETUP_FAILED: 41 showToast('Failed to connect to user profile'); 42 break; 43 case ERROR_CODES.FIREBASE_DOCUMENT_NOT_FOUND: 44 showToast('User profile not found'); 45 break; 46 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 47 showToast('Access denied to user profile'); 48 break; 49 default: 50 showToast('Profile connection error'); 51 } 52 }; 53};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
doc | string | ✅ | Document ID |
onData | (data: DocumentData<T>) => void | ✅ | Data callback |
onError | (error: FirebaseHookError) => void | ✅ | Error handler (required) |
includeMetadataChanges | boolean | ❌ | Include metadata changes |
firebaseProject | string | ❌ | Firebase project name |
1import { 2 useFirestoreTransaction, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const TransferFunds = () => { 7 const { executeBatch, executeTransaction } = useFirestoreTransaction(); 8 9 const batchUpdateUsers = async () => { 10 const operations = [ 11 { 12 type: 'set', 13 collection: 'users', 14 doc: 'user1', 15 data: { name: 'John Doe', status: 'active' }, 16 merge: true, 17 addTimestamp: true, 18 }, 19 { 20 type: 'update', 21 collection: 'users', 22 doc: 'user2', 23 data: { lastLogin: new Date() }, 24 addTimestamp: true, 25 }, 26 { 27 type: 'delete', 28 collection: 'users', 29 doc: 'user3', 30 }, 31 ]; 32 33 const docIds = await executeBatch({ 34 operations, 35 onError: (error) => handleBatchError(error), 36 }); 37 38 if (docIds) { 39 showToast('Batch operation completed successfully'); 40 } 41 }; 42 43 const transferFunds = async (fromUserId, toUserId, amount) => { 44 const result = await executeTransaction({ 45 callback: async (transaction, firestore) => { 46 const fromRef = firestore().collection('accounts').doc(fromUserId); 47 const toRef = firestore().collection('accounts').doc(toUserId); 48 49 const fromDoc = await transaction.get(fromRef); 50 const toDoc = await transaction.get(toRef); 51 52 if (!fromDoc.exists || !toDoc.exists) { 53 throw new Error('Account not found'); 54 } 55 56 const fromBalance = fromDoc.data().balance; 57 const toBalance = toDoc.data().balance; 58 59 if (fromBalance < amount) { 60 throw new Error('Insufficient funds'); 61 } 62 63 transaction.update(fromRef, { balance: fromBalance - amount }); 64 transaction.update(toRef, { balance: toBalance + amount }); 65 66 return { 67 fromBalance: fromBalance - amount, 68 toBalance: toBalance + amount, 69 }; 70 }, 71 onError: (error) => handleTransactionError(error), 72 }); 73 74 if (result) { 75 showToast('Transfer completed successfully'); 76 } 77 }; 78 79 const handleBatchError = (error) => { 80 switch (error.code) { 81 case ERROR_CODES.VALIDATION_OPERATIONS_EMPTY: 82 showToast('No operations provided'); 83 break; 84 case ERROR_CODES.VALIDATION_OPERATIONS_LIMIT_EXCEEDED: 85 showToast('Too many operations (max 500)'); 86 break; 87 case ERROR_CODES.VALIDATION_OPERATION_TYPE_INVALID: 88 showToast('Invalid operation type'); 89 break; 90 case ERROR_CODES.OPERATION_BATCH_FAILED: 91 showToast('Batch operation failed'); 92 break; 93 default: 94 showToast('Batch operation error'); 95 } 96 }; 97 98 const handleTransactionError = (error) => { 99 switch (error.code) { 100 case ERROR_CODES.OPERATION_TRANSACTION_FAILED: 101 showToast('Transaction failed - all changes reverted'); 102 break; 103 case ERROR_CODES.FIREBASE_ABORTED: 104 showToast('Transaction was aborted - please retry'); 105 break; 106 default: 107 showToast('Transaction error'); 108 } 109 }; 110};
Parameter | Type | Required | Description |
---|---|---|---|
operations | BatchOperation[] | ✅ | Array of operations (max 500) |
firebaseProject | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
1interface BatchOperation<T = unknown> { 2 type: 'set' | 'update' | 'delete'; // Operation type 3 collection: string; // Collection name 4 doc: string; // Document ID 5 data?: T; // Data (required for set/update) 6 merge?: boolean; // Merge for set operations 7 addTimestamp?: boolean; // Add server timestamp 8}
Parameter | Type | Required | Description |
---|---|---|---|
callback | (transaction, firestore) => Promise<T> | ✅ | Transaction function |
firebaseProject | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
1const ComplexBatchOperations = () => { 2 const { executeBatch } = useFirestoreTransaction(); 3 4 const performComplexUpdate = async () => { 5 const operations = [ 6 // Set operation with merge 7 { 8 type: 'set', 9 collection: 'users', 10 doc: 'user1', 11 data: { 12 name: 'John Doe', 13 email: 'john@example.com', 14 role: 'admin', 15 }, 16 merge: true, 17 addTimestamp: true, 18 }, 19 // Update operation 20 { 21 type: 'update', 22 collection: 'profiles', 23 doc: 'profile1', 24 data: { 25 lastActive: new Date(), 26 status: 'online', 27 }, 28 addTimestamp: true, 29 }, 30 // Delete operation 31 { 32 type: 'delete', 33 collection: 'temp_data', 34 doc: 'temp1', 35 }, 36 ]; 37 38 const docIds = await executeBatch({ 39 operations, 40 firebaseProject: 'production', // Optional project 41 onError: (error) => handleBatchError(error), 42 }); 43 44 if (docIds) { 45 showToast(`Batch completed: ${docIds.length} operations`); 46 } 47 }; 48 49 const handleBatchError = (error) => { 50 switch (error.code) { 51 case ERROR_CODES.VALIDATION_OPERATIONS_EMPTY: 52 showToast('No operations provided'); 53 break; 54 case ERROR_CODES.VALIDATION_OPERATIONS_LIMIT_EXCEEDED: 55 showToast('Too many operations (max 500 per batch)'); 56 break; 57 case ERROR_CODES.VALIDATION_OPERATION_TYPE_INVALID: 58 showToast('Invalid operation type specified'); 59 break; 60 case ERROR_CODES.VALIDATION_COLLECTION_EMPTY: 61 showToast('Collection name missing in operation'); 62 break; 63 case ERROR_CODES.VALIDATION_DOCUMENT_EMPTY: 64 showToast('Document ID missing in operation'); 65 break; 66 case ERROR_CODES.VALIDATION_DATA_INVALID: 67 showToast('Invalid data for set/update operation'); 68 break; 69 case ERROR_CODES.VALIDATION_DATA_EMPTY: 70 showToast('Empty data for set/update operation'); 71 break; 72 case ERROR_CODES.OPERATION_BATCH_FAILED: 73 showToast('Batch operation failed'); 74 break; 75 default: 76 showToast('Batch operation error'); 77 } 78 }; 79};
1const AdvancedTransaction = () => { 2 const { executeTransaction } = useFirestoreTransaction(); 3 4 const complexTransaction = async () => { 5 const result = await executeTransaction({ 6 callback: async (transaction, firestore) => { 7 // Access multiple documents 8 const userRef = firestore().collection('users').doc('user123'); 9 const accountRef = firestore().collection('accounts').doc('acc123'); 10 const logRef = firestore().collection('logs').doc(); // Auto-generated ID 11 12 // Read operations (must be done first in transactions) 13 const userDoc = await transaction.get(userRef); 14 const accountDoc = await transaction.get(accountRef); 15 16 if (!userDoc.exists || !accountDoc.exists) { 17 throw new Error('Required documents not found'); 18 } 19 20 const userData = userDoc.data(); 21 const accountData = accountDoc.data(); 22 23 // Validation logic 24 if (userData.status !== 'active') { 25 throw new Error('User account is not active'); 26 } 27 28 if (accountData.balance < 100) { 29 throw new Error('Insufficient funds'); 30 } 31 32 // Write operations 33 transaction.update(userRef, { 34 lastTransaction: new Date(), 35 transactionCount: (userData.transactionCount || 0) + 1, 36 }); 37 38 transaction.update(accountRef, { 39 balance: accountData.balance - 100, 40 lastDebit: new Date(), 41 }); 42 43 transaction.set(logRef, { 44 userId: 'user123', 45 action: 'debit', 46 amount: 100, 47 timestamp: new Date(), 48 balanceAfter: accountData.balance - 100, 49 }); 50 51 return { 52 transactionId: logRef.id, 53 newBalance: accountData.balance - 100, 54 success: true, 55 }; 56 }, 57 firebaseProject: 'main', 58 onError: (error) => handleTransactionError(error), 59 }); 60 61 if (result) { 62 showToast(`Transaction completed: ${result.transactionId}`); 63 return result; 64 } 65 }; 66 67 const handleTransactionError = (error) => { 68 switch (error.code) { 69 case ERROR_CODES.VALIDATION_CALLBACK_MISSING: 70 console.error('Transaction callback is required'); 71 break; 72 case ERROR_CODES.OPERATION_TRANSACTION_FAILED: 73 showToast('Transaction failed - all changes reverted'); 74 break; 75 case ERROR_CODES.FIREBASE_ABORTED: 76 showToast('Transaction was aborted - please retry'); 77 break; 78 case ERROR_CODES.FIREBASE_FAILED_PRECONDITION: 79 showToast('Transaction failed due to precondition'); 80 break; 81 default: 82 showToast('Transaction error occurred'); 83 } 84 }; 85};
1import React from 'react'; 2import { 3 useFirestoreRef, 4 ERROR_CODES, 5} from 'akshay-khapare-react-native-firebase-hooks'; 6 7const DocumentOperations = () => { 8 const { getFirestoreReference } = useFirestoreRef(); 9 10 const getDocumentRef = (collection, docId, project) => { 11 try { 12 const docRef = getFirestoreReference(collection, docId, project); 13 return docRef; 14 } catch (error) { 15 handleRefError(error); 16 return null; 17 } 18 }; 19 20 const handleRefError = (error) => { 21 switch (error.code) { 22 case ERROR_CODES.VALIDATION_COLLECTION_EMPTY: 23 showToast('Collection name is required'); 24 break; 25 case ERROR_CODES.VALIDATION_DOCUMENT_EMPTY: 26 showToast('Document ID is required'); 27 break; 28 case ERROR_CODES.VALIDATION_FIELD_INVALID: 29 showToast('Invalid collection or document format'); 30 break; 31 case ERROR_CODES.OPERATION_REFERENCE_FAILED: 32 showToast('Failed to create document reference'); 33 break; 34 default: 35 showToast('Reference creation error'); 36 } 37 }; 38 39 // Example usage in component 40 const createUserReference = () => { 41 const userRef = getDocumentRef('users', 'user123', 'production'); 42 if (userRef) { 43 console.log('Reference created:', userRef.path); 44 } 45 }; 46 47 return ( 48 <View> 49 <TouchableOpacity onPress={createUserReference}> 50 <Text>Create User Reference</Text> 51 </TouchableOpacity> 52 </View> 53 ); 54};
The hook performs comprehensive validation on collection and document names:
//
)/
)/
)/
)1const AdvancedReferenceUsage = () => { 2 const { getFirestoreReference } = useFirestoreRef(); 3 4 const validateAndCreateRef = (collection, docId) => { 5 try { 6 // The hook automatically validates format 7 const ref = getFirestoreReference(collection, docId); 8 9 // Use reference for operations 10 console.log('Reference path:', ref.path); 11 console.log('Collection ID:', ref.parent.id); 12 console.log('Document ID:', ref.id); 13 14 return ref; 15 } catch (error) { 16 // Handle validation errors 17 if (error.code === ERROR_CODES.VALIDATION_FIELD_INVALID) { 18 if (error.message.includes('forward slashes')) { 19 showToast('Document ID cannot contain "/" characters'); 20 } else if (error.message.includes('invalid characters')) { 21 showToast('Collection name has invalid format'); 22 } 23 } 24 return null; 25 } 26 }; 27 28 // Examples of invalid references that will be caught 29 const testInvalidReferences = () => { 30 // These will all throw validation errors: 31 32 // Invalid collection names 33 // validateAndCreateRef('', 'doc1'); // Empty collection 34 // validateAndCreateRef('/users', 'doc1'); // Starts with / 35 // validateAndCreateRef('users/', 'doc1'); // Ends with / 36 // validateAndCreateRef('users//posts', 'doc1'); // Contains // 37 38 // Invalid document IDs 39 // validateAndCreateRef('users', ''); // Empty doc ID 40 // validateAndCreateRef('users', 'user/123'); // Contains / 41 }; 42 43 return ( 44 <View> 45 <TouchableOpacity onPress={() => validateAndCreateRef('users', 'user123')}> 46 <Text>Create Valid Reference</Text> 47 </TouchableOpacity> 48 </View> 49 ); 50};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
doc | string | ✅ | Document ID |
firebaseProjectName | string | ❌ | Firebase project name |
1import { 2 useIsDocumentExist, 3 ERROR_CODES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const DocumentChecker = () => { 7 const { isExist } = useIsDocumentExist(); 8 9 const checkUserExists = async (userId) => { 10 const exists = await isExist({ 11 collection: 'users', 12 doc: userId, 13 source: 'server', // Force server check 14 onError: (error) => handleExistsError(error, userId), 15 }); 16 17 if (exists !== null) { 18 return exists ? 'User exists' : 'User not found'; 19 } 20 return 'Check failed'; 21 }; 22 23 const handleExistsError = (error, userId) => { 24 switch (error.code) { 25 case ERROR_CODES.VALIDATION_SOURCE_INVALID: 26 showToast('Invalid data source specified'); 27 break; 28 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 29 showToast('Access denied'); 30 break; 31 case ERROR_CODES.OPERATION_GET_FAILED: 32 showToast('Failed to check user existence'); 33 logError('Existence check failed', { userId, error }); 34 break; 35 default: 36 showToast('Existence check error'); 37 } 38 }; 39};
Parameter | Type | Required | Description |
---|---|---|---|
collection | string | ✅ | Collection name |
doc | string | ✅ | Document ID |
source | 'default' | 'server' | 'cache' | ❌ | Data source |
firebaseProject | string | ❌ | Firebase project name |
onError | (error: FirebaseHookError) => void | ❌ | Error handler |
1import { 2 ERROR_CATEGORIES, 3 ERROR_CODES, 4 ERROR_CODE_NUMBERS, 5} from 'akshay-khapare-react-native-firebase-hooks'; 6 7// Available categories 8ERROR_CATEGORIES.VALIDATION; // Input validation errors 9ERROR_CATEGORIES.FIREBASE; // Firebase-specific errors 10ERROR_CATEGORIES.NETWORK; // Network connectivity errors 11ERROR_CATEGORIES.INITIALIZATION; // Setup and config errors 12ERROR_CATEGORIES.OPERATION; // CRUD operation errors 13ERROR_CATEGORIES.LISTENER; // Real-time listener errors
Code | Number | Description |
---|---|---|
VALIDATION_COLLECTION_EMPTY | 1001 | Collection name is empty |
VALIDATION_DOCUMENT_EMPTY | 1002 | Document ID is empty |
VALIDATION_DATA_INVALID | 1003 | Invalid data format |
VALIDATION_DATA_EMPTY | 1004 | Data object is empty |
VALIDATION_CALLBACK_MISSING | 1005 | Required callback missing |
VALIDATION_CALLBACK_INVALID | 1006 | Invalid callback function |
VALIDATION_FIELD_MISSING | 1007 | Required field missing |
VALIDATION_FIELD_INVALID | 1008 | Invalid field format |
VALIDATION_LIMIT_INVALID | 1009 | Invalid limit value |
VALIDATION_OPERATIONS_EMPTY | 1010 | Operations array is empty |
VALIDATION_OPERATIONS_LIMIT_EXCEEDED | 1011 | Too many operations (>500) |
VALIDATION_OPERATION_TYPE_INVALID | 1012 | Invalid operation type |
VALIDATION_WHERE_CLAUSE_INVALID | 1013 | Invalid where condition |
VALIDATION_ORDER_BY_INVALID | 1014 | Invalid orderBy condition |
VALIDATION_PROJECT_NAME_EMPTY | 1015 | Project name is empty |
VALIDATION_CONFIG_MISSING | 1016 | Configuration missing |
VALIDATION_CONFIG_FIELD_MISSING | 1017 | Config field missing |
VALIDATION_SOURCE_INVALID | 1018 | Invalid data source |
Code | Number | Description |
---|---|---|
FIREBASE_APP_NOT_INITIALIZED | 2001 | Firebase app not initialized |
FIREBASE_PROJECT_NOT_FOUND | 2002 | Firebase project not found |
FIREBASE_DOCUMENT_NOT_FOUND | 2003 | Document not found |
FIREBASE_COLLECTION_NOT_FOUND | 2004 | Collection not found |
FIREBASE_PERMISSION_DENIED | 2005 | Permission denied |
FIREBASE_QUOTA_EXCEEDED | 2006 | Quota exceeded |
FIREBASE_INVALID_ARGUMENT | 2007 | Invalid argument |
FIREBASE_FAILED_PRECONDITION | 2008 | Failed precondition |
FIREBASE_ABORTED | 2009 | Operation aborted |
FIREBASE_OUT_OF_RANGE | 2010 | Out of range |
FIREBASE_UNIMPLEMENTED | 2011 | Unimplemented |
FIREBASE_INTERNAL | 2012 | Internal error |
FIREBASE_UNAVAILABLE | 2013 | Service unavailable |
FIREBASE_DATA_LOSS | 2014 | Data loss |
FIREBASE_UNAUTHENTICATED | 2015 | User not authenticated |
Code | Number | Description |
---|---|---|
NETWORK_UNAVAILABLE | 3001 | Network unavailable |
NETWORK_TIMEOUT | 3002 | Network timeout |
NETWORK_CONNECTION_FAILED | 3003 | Connection failed |
NETWORK_DNS_FAILURE | 3004 | DNS failure |
Code | Number | Description |
---|---|---|
INIT_FIREBASE_FAILED | 4001 | Firebase initialization failed |
INIT_FIRESTORE_FAILED | 4002 | Firestore initialization failed |
INIT_CONFIG_INVALID | 4003 | Invalid configuration |
INIT_PROJECT_EXISTS | 4004 | Project already exists |
INIT_CACHE_SIZE_INVALID | 4005 | Invalid cache size |
Code | Number | Description |
---|---|---|
OPERATION_SET_FAILED | 5001 | Set operation failed |
OPERATION_GET_FAILED | 5002 | Get operation failed |
OPERATION_UPDATE_FAILED | 5003 | Update operation failed |
OPERATION_DELETE_FAILED | 5004 | Delete operation failed |
OPERATION_QUERY_FAILED | 5005 | Query operation failed |
OPERATION_BATCH_FAILED | 5006 | Batch operation failed |
OPERATION_TRANSACTION_FAILED | 5007 | Transaction failed |
OPERATION_REFERENCE_FAILED | 5008 | Reference creation failed |
Code | Number | Description |
---|---|---|
LISTENER_SETUP_FAILED | 6001 | Listener setup failed |
LISTENER_DATA_PROCESSING_FAILED | 6002 | Data processing failed |
LISTENER_UNSUBSCRIBE_FAILED | 6003 | Unsubscribe failed |
LISTENER_SNAPSHOT_ERROR | 6004 | Snapshot error |
Code | Number | Description |
---|---|---|
UNKNOWN_ERROR | 9001 | Unknown error occurred |
1import { 2 ERROR_CODES, 3 ERROR_CATEGORIES, 4} from 'akshay-khapare-react-native-firebase-hooks'; 5 6const globalErrorHandler = (error) => { 7 // Log to analytics 8 logToAnalytics('firebase_error', { 9 code: error.code, 10 codeNumber: error.codeNumber, 11 category: error.category, 12 message: error.message, 13 timestamp: error.timestamp, 14 details: error.details, 15 }); 16 17 // Handle by category 18 switch (error.category) { 19 case ERROR_CATEGORIES.VALIDATION: 20 showToast('Please check your input and try again'); 21 break; 22 case ERROR_CATEGORIES.FIREBASE: 23 handleFirebaseError(error); 24 break; 25 case ERROR_CATEGORIES.NETWORK: 26 showToast('Network error. Please check your connection.'); 27 break; 28 case ERROR_CATEGORIES.OPERATION: 29 showToast('Operation failed. Please try again.'); 30 break; 31 default: 32 showToast('An unexpected error occurred'); 33 } 34}; 35 36const handleFirebaseError = (error) => { 37 switch (error.code) { 38 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 39 redirectToLogin(); 40 break; 41 case ERROR_CODES.FIREBASE_QUOTA_EXCEEDED: 42 showMaintenanceMessage(); 43 break; 44 case ERROR_CODES.FIREBASE_UNAUTHENTICATED: 45 refreshAuth(); 46 break; 47 default: 48 showToast('Firebase service error'); 49 } 50};
1const retryableErrorCodes = [ 2 ERROR_CODES.NETWORK_UNAVAILABLE, 3 ERROR_CODES.FIREBASE_UNAVAILABLE, 4 ERROR_CODES.FIREBASE_ABORTED, 5]; 6 7const withRetry = async (operation, maxRetries = 3) => { 8 let lastError; 9 10 for (let attempt = 1; attempt <= maxRetries; attempt++) { 11 try { 12 const result = await operation({ 13 onError: (error) => { 14 lastError = error; 15 if (!retryableErrorCodes.includes(error.code)) { 16 throw error; // Don't retry non-retryable errors 17 } 18 }, 19 }); 20 21 if (result !== null) return result; // Success 22 23 if ( 24 attempt < maxRetries && 25 retryableErrorCodes.includes(lastError?.code) 26 ) { 27 await delay(Math.pow(2, attempt) * 1000); // Exponential backoff 28 continue; 29 } 30 31 throw lastError; 32 } catch (error) { 33 if (attempt === maxRetries) throw error; 34 } 35 } 36}; 37 38// Usage 39const data = await withRetry(() => 40 getData({ 41 collection: 'users', 42 doc: 'user123', 43 }) 44);
1const productionErrorHandler = (error) => { 2 // Send to crash reporting service 3 crashAnalytics.recordError(error, { 4 errorCode: error.code, 5 errorNumber: error.codeNumber, 6 category: error.category, 7 context: error.details, 8 }); 9 10 // Send to custom logging service 11 logService.error('Firebase Hook Error', { 12 code: error.code, 13 message: error.message, 14 timestamp: error.timestamp, 15 userID: getCurrentUserId(), 16 sessionID: getSessionId(), 17 appVersion: getAppVersion(), 18 details: error.details, 19 }); 20 21 // Update error metrics 22 errorMetrics.increment(`firebase_error.${error.category}.${error.code}`); 23};
1import { useFirestoreGet, useCollectionListener, ERROR_CODES } from 'akshay-khapare-react-native-firebase-hooks'; 2 3const SmartDataLoader = ({ collection, doc, realTime = false }) => { 4 const { getData } = useFirestoreGet(); 5 const { listenToCollection } = useCollectionListener(); 6 const [data, setData] = useState(null); 7 const [loading, setLoading] = useState(true); 8 const [error, setError] = useState(null); 9 10 const handleError = useCallback((error) => { 11 setError(error); 12 setLoading(false); 13 14 // Production error handling 15 switch (error.code) { 16 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 17 trackEvent('access_denied', { collection, doc }); 18 break; 19 case ERROR_CODES.FIREBASE_QUOTA_EXCEEDED: 20 trackEvent('quota_exceeded', { collection }); 21 notifyDevTeam('Quota exceeded', error.details); 22 break; 23 default: 24 trackEvent('data_load_error', { 25 collection, 26 doc, 27 errorCode: error.code 28 }); 29 } 30 }, [collection, doc]); 31 32 useEffect(() => { 33 if (realTime && !doc) { 34 // Real-time collection 35 const unsubscribe = listenToCollection({ 36 collection, 37 onData: (data) => { 38 setData(data); 39 setLoading(false); 40 setError(null); 41 }, 42 onError: handleError 43 }); 44 return unsubscribe; 45 } else if (doc) { 46 // Single document fetch 47 const fetchData = async () => { 48 setLoading(true); 49 const result = await getData({ 50 collection, 51 doc, 52 onError: handleError 53 }); 54 55 if (result) { 56 setData(result); 57 setLoading(false); 58 setError(null); 59 } 60 }; 61 62 fetchData(); 63 } 64 }, [collection, doc, realTime, getData, listenToCollection, handleError]); 65 66 if (loading) return <LoadingSpinner />; 67 if (error) return <ErrorDisplay error={error} onRetry={() => { 68 setLoading(true); 69 setError(null); 70 // Trigger re-fetch by updating a state or calling fetch function again 71 }} />; 72 73 return <DataDisplay data={data} />; 74};
1const AutoSaveForm = ({ collection, doc, initialData }) => { 2 const { setData } = useFirestoreSet(); 3 const { updateData } = useFirestoreUpdate(); 4 const [formData, setFormData] = useState(initialData); 5 const [saveStatus, setSaveStatus] = useState('saved'); 6 7 const autoSave = useCallback( 8 debounce(async (data) => { 9 setSaveStatus('saving'); 10 11 const operation = doc ? updateData : setData; 12 const result = await operation({ 13 collection, 14 doc: doc || generateId(), 15 data, 16 addTimestamp: true, 17 onError: (error) => { 18 setSaveStatus('error'); 19 handleFormError(error, data); 20 } 21 }); 22 23 if (result) { 24 setSaveStatus('saved'); 25 trackEvent('auto_save_success', { collection, doc }); 26 } 27 }, 2000), 28 [collection, doc, setData, updateData] 29 ); 30 31 const handleFormError = (error, data) => { 32 switch (error.code) { 33 case ERROR_CODES.VALIDATION_DATA_EMPTY: 34 // Don't show error for empty auto-save 35 break; 36 case ERROR_CODES.FIREBASE_PERMISSION_DENIED: 37 showToast('Permission denied. Changes not saved.'); 38 break; 39 case ERROR_CODES.FIREBASE_QUOTA_EXCEEDED: 40 showToast('Storage limit reached. Please contact support.'); 41 break; 42 default: 43 showToast('Auto-save failed. Your changes may be lost.'); 44 // Backup to AsyncStorage (React Native) or SecureStore 45 AsyncStorage.setItem(`backup_${collection}_${doc}`, JSON.stringify(data)); 46 } 47 }; 48 49 useEffect(() => { 50 if (formData !== initialData) { 51 autoSave(formData); 52 } 53 }, [formData, initialData, autoSave]); 54 55 return ( 56 <View> 57 <SaveStatus status={saveStatus} /> 58 {/* Form fields using TextInput, TouchableOpacity, etc. */} 59 </View> 60 ); 61};
source: 'cache'
for better performance when appropriateincludeMetadataChanges: false
unless you need metadata updatesonError
callbacks in productionWe welcome contributions! Please read our Contributing Guide for details.
MIT © Akshay Khapare
Made with ❤️ for the React Native community
No vulnerabilities found.
No security vulnerabilities found.