akshay-khapare-expo-firebase-hooks
v1.0.2
Published
Production-ready Firebase hooks for Expo React Native applications with comprehensive error handling
Downloads
14
Maintainers
Readme
akshay-khapare-expo-firebase-hooks
Production-ready Firebase hooks for Expo React Native applications with comprehensive error handling and TypeScript support.
🚀 Features
- Simple & Direct: Clean API with direct error throwing and data returns
- Production Ready: Optimized for real-world applications
- Type Safe: Full TypeScript support with function-level generics
- Comprehensive Error Handling: All Firebase errors are properly caught and thrown with detailed messages
- Modern React: Uses latest React hooks patterns (no useCallback - add in parent as needed)
- Expo Compatible: Designed specifically for Expo React Native
- Performance Optimized: Efficient listeners and memory management
- Dual Approach: Direct returns for operations, callbacks for real-time listeners
📦 Installation
npm install akshay-khapare-expo-firebase-hooksPeer Dependencies
npm install react react-native firebase🔧 Setup
Initialize Firebase once in your app:
import { firebaseInit } from 'akshay-khapare-expo-firebase-hooks';
firebaseInit({
projects: [
{
projectName: 'main-project',
config: {
apiKey: 'your-api-key',
authDomain: 'your-project.firebaseapp.com',
projectId: 'your-project-id',
storageBucket: 'your-project.appspot.com',
messagingSenderId: '123456789',
appId: '1:123456789:web:abcdef123456',
},
},
],
});🎯 Quick Start Example
interface User {
id: string;
name: string;
email: string;
status: 'online' | 'offline';
}
function MyComponent() {
const { getDocument } = useFirestoreGetDoc();
const { addDocument } = useFirestoreAdd();
const [loading, setLoading] = useState(false);
const handleGetUser = async () => {
try {
setLoading(true);
const user = await getDocument<User>({
projectName: 'main-project',
collectionName: 'users',
documentId: 'user123',
});
console.log('User:', user?.name);
} catch (error) {
console.error('Error:', error.message);
} finally {
setLoading(false);
}
};
const handleAddUser = async () => {
try {
const result = await addDocument({
projectName: 'main-project',
collectionName: 'users',
data: { name: 'John', email: '[email protected]' },
});
console.log('Added user with ID:', result.id);
Alert.alert('Success', `User created with ID: ${result.id}`);
} catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Error', 'You do not have permission to add users.');
} else {
Alert.alert('Error', 'Failed to add user: ' + error.message);
}
} finally {
setLoading(false);
}
};
return (
<View>
<Button title="Get User" onPress={handleGetUser} />
<Button title="Add User" onPress={handleAddUser} />
</View>
);
}🎣 Available Hooks
📝 Document Operations
Add documents to any Firestore collection. Returns the document ID directly.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namedata: Record<string, unknown> - Document data to add
Returns: Promise<{ id: string }> - The newly created document ID
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Parameter Validation: Throws if
collectionNameordataare invalid. - Permission Denied: User does not have permission to write to the specified collection.
- Network Errors: Device is offline or has unstable connectivity.
import { useFirestoreAdd, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
function AddUserComponent() {
const { addDocument } = useFirestoreAdd();
const [loading, setLoading] = useState(false);
const handleAddUser = async () => {
try {
setLoading(true);
const result = await addDocument({
projectName: 'main-project',
collectionName: 'users',
data: {
name: 'John',
email: '[email protected]',
status: 'online',
createdAt: new Date().toISOString(),
},
});
console.log('User added with ID:', result.id);
Alert.alert('Success', `User created with ID: ${result.id}`);
} catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Error', 'You do not have permission to add users.');
} else {
Alert.alert('Error', 'Failed to add user: ' + error.message);
}
} finally {
setLoading(false);
}
};
return (
<TouchableOpacity onPress={handleAddUser} disabled={loading}>
<Text>{loading ? 'Adding...' : 'Add User'}</Text>
</TouchableOpacity>
);
}Error Handling:
- Parameter validation errors (missing/invalid data)
- Permission denied errors
- Network connectivity issues
- Firestore service unavailable
- Invalid document structure
Set documents with specific IDs (creates or overwrites). No return value.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namedocumentId: string - Document ID to setdata: Record<string, unknown> - Document datamerge: boolean (optional) - Whether to merge with existing data (default: false)
Returns: Promise<void>
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Parameter Validation: Throws if
collectionName,documentId, ordataare invalid (INVALID_ARGUMENT). - Permission Denied: User does not have permission to write to the specified document (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreSet, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
function SetUserComponent() {
const { setDocument } = useFirestoreSet();
const [isUpdating, setIsUpdating] = useState(false);
const handleSetUser = async () => {
try {
setIsUpdating(true);
await setDocument({
projectName: 'main-project',
collectionName: 'users',
documentId: 'user123',
data: {
name: 'John Updated',
email: '[email protected]',
updatedAt: new Date().toISOString(),
},
merge: true, // Merge with existing data
});
Alert.alert('Success', 'User updated successfully!');
} catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Error', 'You are not allowed to edit this user.');
} else {
Alert.alert('Error', 'Failed to update user: ' + error.message);
}
} finally {
setIsUpdating(false);
}
};
return (
<Button
title={isUpdating ? "Updating..." : "Set User"}
onPress={handleSetUser}
disabled={isUpdating}
/>
);
}Update existing documents. Only updates specified fields.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namedocumentId: string - Document ID to updatedata: Record<string, unknown> - Fields to update
Returns: Promise<void>
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Document Not Found: The hook will throw an error if the document at the specified path does not exist (
DOCUMENT_NOT_FOUND). - Parameter Validation: Throws if
collectionName,documentId, ordataare invalid (INVALID_ARGUMENT). - Permission Denied: User does not have permission to update the specified document (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreUpdate, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
function UpdateUserComponent() {
const { updateDocument } = useFirestoreUpdate();
const [loading, setLoading] = useState(false);
const handleUpdateUserStatus = async (status: 'online' | 'offline') => {
try {
setLoading(true);
await updateDocument({
projectName: 'main-project',
collectionName: 'users',
documentId: 'user123',
data: {
status,
lastSeen: new Date().toISOString(),
},
});
console.log('User status updated to:', status);
} catch (error) {
if (error.code === FirebaseErrorCode.DOCUMENT_NOT_FOUND) {
Alert.alert('Not Found', 'This user does not exist and cannot be updated.');
} else {
Alert.alert('Update Error', error.message);
}
} finally {
setLoading(false);
}
};
return (
<View>
<Button
title="Set Online"
onPress={() => handleUpdateUserStatus('online')}
disabled={loading}
/>
<Button
title="Set Offline"
onPress={() => handleUpdateUserStatus('offline')}
disabled={loading}
/>
</View>
);
}Delete documents from Firestore permanently.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namedocumentId: string - Document ID to delete
Returns: Promise<void>
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Parameter Validation: Throws if
collectionNameordocumentIdare invalid (INVALID_ARGUMENT). - Permission Denied: User does not have permission to delete the specified document (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreDelete, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
function DeleteUserComponent() {
const { deleteDocument } = useFirestoreDelete();
const [deleting, setDeleting] = useState(false);
const handleDeleteUser = async (userId: string) => {
try {
// Confirm deletion
Alert.alert(
'Confirm Delete',
'Are you sure you want to delete this user?',
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Delete',
style: 'destructive',
onPress: async () => {
try {
setDeleting(true);
await deleteDocument({
projectName: 'main-project',
collectionName: 'users',
documentId: userId,
});
Alert.alert('Success', 'User deleted successfully');
} catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Error', 'You do not have permission to delete this user.');
} else {
Alert.alert('Delete Error', error.message);
}
} finally {
setDeleting(false);
}
}
}
]
);
} catch (error) {
console.error('Delete failed:', error.message);
}
};
return (
<Button
title={deleting ? "Deleting..." : "Delete User"}
onPress={() => handleDeleteUser('user123')}
disabled={deleting}
color="red"
/>
);
}📖 Data Retrieval
Fetch a single document from Firestore. Returns the document data or null if not found.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namedocumentId: string - Document ID to fetch
Returns: Promise<T | null> - Document data with ID field added, or null if not found
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Parameter Validation: Throws if
collectionNameordocumentIdare invalid (INVALID_ARGUMENT). - Permission Denied: User does not have permission to read from the specified location (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreGetDoc, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
interface User {
id: string;
name: string;
email: string;
status: 'online' | 'offline';
}
function GetUserComponent() {
const { getDocument } = useFirestoreGetDoc();
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(false);
const fetchUser = async (userId: string) => {
try {
setLoading(true);
const userData = await getDocument<User>({
projectName: 'main-project',
collectionName: 'users',
documentId: userId,
});
if (userData) {
console.log('Found user:', userData.name);
setUser(userData);
} else {
console.log('User not found');
Alert.alert('Not Found', 'User does not exist');
}
} catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Error', 'You do not have access to this user\'s data.');
} else {
Alert.alert('Error', 'Failed to fetch user: ' + error.message);
}
} finally {
setLoading(false);
}
};
return (
<View>
<Button
title={loading ? "Loading..." : "Fetch User"}
onPress={() => fetchUser('user123')}
disabled={loading}
/>
{user && (
<View>
<Text>Name: {user.name}</Text>
<Text>Email: {user.email}</Text>
<Text>Status: {user.status}</Text>
</View>
)}
</View>
);
}Fetch multiple documents from a collection with optional query constraints.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namequeries: QueryConstraint[] (optional) - Firestore query constraints
Returns: Promise<T[]> - Array of documents with ID fields added
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Parameter Validation: Throws if
collectionNameis invalid (INVALID_ARGUMENT). - Invalid Queries: One of the provided
queriesis malformed (e.g., incorrect field path or operator) (INVALID_ARGUMENT). - Permission Denied: User does not have permission to query the collection (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreGetCollection, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
import { where, orderBy, limit } from 'firebase/firestore';
interface User {
id: string;
name: string;
email: string;
status: 'online' | 'offline';
createdAt: string;
}
function GetUsersComponent() {
const { getCollection } = useFirestoreGetCollection();
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(false);
const fetchOnlineUsers = async () => {
try {
setLoading(true);
const userData = await getCollection<User>({
projectName: 'main-project',
collectionName: 'users',
queries: [
where('status', '==', 'online'),
orderBy('createdAt', 'desc'),
limit(10)
],
});
console.log('Found', userData.length, 'online users');
setUsers(userData);
} catch (error) {
if (error.code === FirebaseErrorCode.INVALID_ARGUMENT) {
Alert.alert('Query Error', 'There is an issue with the query constraints.');
} else {
Alert.alert('Error', 'Failed to fetch users: ' + error.message);
}
} finally {
setLoading(false);
}
};
const fetchAllUsers = async () => {
try {
setLoading(true);
const userData = await getCollection<User>({
projectName: 'main-project',
collectionName: 'users',
// No queries = fetch all documents
});
setUsers(userData);
} catch (error) {
console.error('Fetch failed:', error.message);
} finally {
setLoading(false);
}
};
return (
<View>
<Button title="Fetch Online Users" onPress={fetchOnlineUsers} />
<Button title="Fetch All Users" onPress={fetchAllUsers} />
{loading && <Text>Loading...</Text>}
<FlatList
data={users}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View>
<Text>{item.name} - {item.status}</Text>
</View>
)}
/>
</View>
);
}Check if a document exists without fetching its data.
Parameters:
projectName: string - Firebase project identifiercollectionName: string - Firestore collection namedocumentId: string - Document ID to check
Returns: Promise<boolean> - true if document exists, false otherwise
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Parameter Validation: Throws if
collectionNameordocumentIdare invalid (INVALID_ARGUMENT). - Permission Denied: User does not have permission to access the document path (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreDocumentExists, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
function CheckUserComponent() {
const { checkDocumentExists } = useFirestoreDocumentExists();
const [checking, setChecking] = useState(false);
const checkUserExists = async (userId: string) => {
try {
setChecking(true);
const exists = await checkDocumentExists({
projectName: 'main-project',
collectionName: 'users',
documentId: userId,
});
if (exists) {
Alert.alert('Found', 'User exists in database');
} else {
Alert.alert('Not Found', 'User does not exist');
}
} catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Error', 'You do not have permission to check this user.');
} else {
Alert.alert('Error', 'Failed to check user: ' + error.message);
}
} finally {
setChecking(false);
}
};
return (
<Button
title={checking ? "Checking..." : "Check User Exists"}
onPress={() => checkUserExists('user123')}
disabled={checking}
/>
);
}🔄 Real-time Listeners
Listens for real-time updates to a single document in a Firestore collection. The hook manages the subscription lifecycle and automatically unsubscribes on unmount.
Parameters
DocumentListenerParams<T>: An object containing:projectName(string): The Firebase project name.collectionName(string): The name of the collection.documentId(string): The ID of the document to listen to.onSuccess((data: T | null) => void): Callback for successful updates. Receives the document data (withid) ornullif it doesn't exist.onError((error: FirebaseHookError) => void): Callback for handling errors.
Returns
unsubscribe(function): A function that can be called to manually stop the listener.
Potential Errors (via onError callback)
- Parameter Validation: Invalid
collectionNameordocumentId(INVALID_ARGUMENT). - Permission Denied: The user does not have permission to listen to the specified document (
PERMISSION_DENIED). - Network Errors: The device loses connectivity (
NETWORK_ERROR).
Usage Example
import React, { useState, useEffect } from 'react';
import {
useFirestoreDocumentListener,
FirebaseErrorCode,
} from 'akshay-khapare-expo-firebase-hooks';
const UserProfile = ({ userId }) => {
const [user, setUser] = useState(null);
const [error, setError] = useState(null);
const unsubscribe = useFirestoreDocumentListener({
projectName: 'my-project',
collectionName: 'users',
documentId: userId,
onSuccess: data => {
console.log('Received real-time update:', data);
setUser(data);
},
onError: err => {
console.error('Listener Error:', err);
if (err.code === FirebaseErrorCode.PERMISSION_DENIED) {
setError('You do not have permission to view this profile.');
} else {
setError(err.message);
}
},
});
// You can manually unsubscribe if needed, e.g., on a button click
// useEffect(() => {
// return () => unsubscribe();
// }, [unsubscribe]);
if (error) {
return <p>Error: {error}</p>;
}
return (
<div>
<h2>User Profile (Real-time)</h2>
{user ? (
<pre>{JSON.stringify(user, null, 2)}</pre>
) : (
<p>Loading user...</p>
)}
</div>
);
};Listens for real-time updates to a collection in Firestore, with optional queries. The hook manages the subscription lifecycle and automatically unsubscribes on unmount.
Parameters
CollectionListenerParams<T>: An object containing:projectName(string): The Firebase project name.collectionName(string): The name of the collection.queries(QueryConstraint[] - optional): An array of Firestore queries (where,orderBy,limit).onSuccess((data: T[]) => void): Callback for successful updates. Receives an array of document data (withid).onError((error: FirebaseHookError) => void): Callback for handling errors.
Returns
unsubscribe(function): A function that can be called to manually stop the listener.
Potential Errors (via onError callback)
- Parameter Validation: Invalid
collectionName(INVALID_ARGUMENT). - Invalid Queries: A query constraint is malformed or references an index that does not exist (
INVALID_ARGUMENT). - Permission Denied: The user does not have permission to listen to the specified collection (
PERMISSION_DENIED). - Network Errors: The device loses connectivity (
NETWORK_ERROR).
Usage Example
import React, { useState, useEffect } from 'react';
import {
useFirestoreCollectionListener,
FirebaseErrorCode,
} from 'akshay-khapare-expo-firebase-hooks';
import { where, orderBy } from 'firebase/firestore';
const ActiveUsersList = () => {
const [users, setUsers] = useState([]);
const [error, setError] = useState(null);
const unsubscribe = useFirestoreCollectionListener({
projectName: 'my-project',
collectionName: 'users',
queries: [where('status', '==', 'active'), orderBy('lastSeen', 'desc')],
onSuccess: data => {
console.log('Received real-time collection update:', data);
setUsers(data);
},
onError: err => {
console.error('Listener Error:', err);
if (err.code === FirebaseErrorCode.PERMISSION_DENIED) {
setError('You do not have permission to view this list of users.');
} else if (err.code === FirebaseErrorCode.INVALID_ARGUMENT) {
setError('The query is invalid. Please check the constraints.');
} else {
setError(err.message);
}
},
});
if (error) {
return <p>Error: {error}</p>;
}
return (
<div>
<h2>Active Users (Real-time)</h2>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};⚡ Batch Operations
Execute multiple Firestore operations in a single atomic transaction.
Parameters:
operations: BatchOperation[] - Array of operations to execute
Returns: Promise<void>
Throws: FirebaseHookError - For any Firebase operation errors
Potential Errors:
- Invalid Operations: The
operationsarray is empty or an operation object is missing required fields (type,collectionName, etc.) (INVALID_ARGUMENT). - Error in Single Operation: The error message will specify the index of the operation that failed (e.g., due to invalid data or a non-existent document for an 'update' operation) (
INVALID_ARGUMENT). - Permission Denied: User does not have permission for one of the operations in the batch (
PERMISSION_DENIED). - Network Errors: Device is offline or has unstable connectivity (
NETWORK_ERROR).
import { useFirestoreTransaction, FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
function BatchOperationsComponent() {
const { executeBatch } = useFirestoreTransaction();
const [processing, setProcessing] = useState(false);
const performBatchOperations = async () => {
try {
setProcessing(true);
await executeBatch({
operations: [
{
type: 'set',
projectName: 'main-project',
collectionName: 'users',
documentId: 'user1',
data: { name: 'John', status: 'online' },
merge: true,
},
{
type: 'update',
projectName: 'main-project',
collectionName: 'users',
documentId: 'user2',
data: { lastSeen: new Date().toISOString() },
},
{
type: 'delete',
projectName: 'main-project',
collectionName: 'users',
documentId: 'user3',
},
],
});
Alert.alert('Success', 'Batch operations completed!');
} catch (error) {
if (error.code === FirebaseErrorCode.INVALID_ARGUMENT) {
Alert.alert('Invalid Operation', error.message);
} else if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Permission Denied', 'You do not have permission for one of the operations in the batch.');
} else {
Alert.alert('Batch Error', error.message);
}
} finally {
setProcessing(false);
}
};
return (
<Button
title={processing ? "Processing..." : "Execute Batch"}
onPress={performBatchOperations}
disabled={processing}
/>
);
}🚨 Error Handling
All hooks use comprehensive error handling that covers:
Error Types
All thrown errors are instances of FirebaseHookError and will have a code property that corresponds to the FirebaseErrorCode enum. You should import and use this enum for type-safe error checking.
FirebaseErrorCode.INVALID_ARGUMENT: Missing or invalid parameters passed to a hook.FirebaseErrorCode.PERMISSION_DENIED: User does not have permission according to Firestore security rules.FirebaseErrorCode.NETWORK_ERROR: The device is offline or the connection is unstable.FirebaseErrorCode.DOCUMENT_NOT_FOUND: A document specified for an update or delete operation does not exist.FirebaseErrorCode.OPERATION_FAILED: A generic failure from the Firebase SDK.FirebaseErrorCode.UNKNOWN_ERROR: An unexpected error occurred.
Error Structure
import { FirebaseErrorCode } from 'akshay-khapare-expo-firebase-hooks';
interface FirebaseHookError extends Error {
message: string; // Human-readable error message
code?: string; // Firebase error code
originalError?: Error; // Original Firebase error object
}Best Practices
- Always use try-catch for operations:
try {
const result = await addDocument({ ... });
// Handle success
} catch (error) {
// Handle error
console.error('Operation failed:', error.message);
}- Check for specific error types:
catch (error) {
if (error.code === FirebaseErrorCode.PERMISSION_DENIED) {
Alert.alert('Access Denied', 'You don\'t have permission for this action');
} else if (error.code === FirebaseErrorCode.DOCUMENT_NOT_FOUND) {
Alert.alert('Not Found', 'The requested document doesn\'t exist');
} else {
Alert.alert('Error', error.message);
}
}- Use loading states:
const [loading, setLoading] = useState(false);
const handleOperation = async () => {
setLoading(true);
try {
await performOperation();
} finally {
setLoading(false); // Always reset loading
}
};- Cleanup listeners:
The listener hooks (useFirestoreDocumentListener, useFirestoreCollectionListener) automatically clean up their subscriptions when the component unmounts. You can also call the returned unsubscribe function manually if you need to stop listening earlier.
useEffect(
() => {
const unsubscribe = useFirestoreDocumentListener({
// ... params
});
// The listener is active.
return () => {
unsubscribe(); // This is called on unmount.
};
},
[
/* dependencies */
]
);🔧 TypeScript Support
Full TypeScript support with generics for type-safe data handling:
interface User {
id: string;
name: string;
email: string;
}
// Type-safe document retrieval
const user = await getDocument<User>({ ... }); // user is User | null
// Type-safe collection retrieval
const users = await getCollection<User>({ ... }); // users is User[]
// Type-safe listeners
useFirestoreDocumentListener<User>({
onSuccess: (user) => {
// user is typed as User | null
}
});📱 Performance Tips
- Add useCallback in parent components as needed:
const handleAddUser = useCallback(async () => {
// Your operation
}, [dependencies]);- Implement proper cleanup:
Listener hooks automatically handle cleanup. If you need to stop listening based on some application logic, you can call the unsubscribe function that the hook returns.
const unsubscribe = useFirestoreCollectionListener({ ... });
// Later, perhaps in a button press handler:
const handleStopListening = () => {
unsubscribe();
};- Use appropriate queries:
// Good: Limited results
const users = await getCollection({
queries: [limit(20), where('active', '==', true)],
});
// Avoid: Fetching all documents
const users = await getCollection({});📄 License
MIT License - see LICENSE file for details.
🤝 Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests.
🐛 Issues
Found a bug? Please open an issue with detailed reproduction steps.
