or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-types.mddatabase-operations.mdindex.mdmodular-api.mdoffline-network.mdquerying-filtering.mdrealtime-sync.mdtransactions-batches.md

offline-network.mddocs/

0

# Offline & Network Management

1

2

Comprehensive offline support with configurable persistence, network management, and cache control.

3

4

## Capabilities

5

6

### Network Control

7

8

Manage network connectivity to control when Firestore communicates with the server.

9

10

```typescript { .api }

11

/**

12

* Enable network connectivity for Firestore

13

* @returns Promise resolving when network is enabled

14

*/

15

enableNetwork(): Promise<void>;

16

17

/**

18

* Disable network connectivity for Firestore

19

* @returns Promise resolving when network is disabled

20

*/

21

disableNetwork(): Promise<void>;

22

```

23

24

**Usage Examples:**

25

26

```typescript

27

import firestore from '@react-native-firebase/firestore';

28

29

// Enable network (default state)

30

await firestore().enableNetwork();

31

console.log('Network enabled - can sync with server');

32

33

// Disable network for offline-only operation

34

await firestore().disableNetwork();

35

console.log('Network disabled - operating in offline mode');

36

37

// Re-enable network

38

await firestore().enableNetwork();

39

console.log('Network re-enabled - will sync pending changes');

40

41

// Network state management based on app state

42

import { AppState } from 'react-native';

43

44

class NetworkManager {

45

constructor() {

46

AppState.addEventListener('change', this.handleAppStateChange);

47

}

48

49

handleAppStateChange = async (nextAppState: string) => {

50

const db = firestore();

51

52

if (nextAppState === 'background') {

53

// Disable network to save battery/data when app is backgrounded

54

await db.disableNetwork();

55

console.log('App backgrounded - network disabled');

56

} else if (nextAppState === 'active') {

57

// Re-enable network when app becomes active

58

await db.enableNetwork();

59

console.log('App active - network enabled');

60

}

61

};

62

}

63

```

64

65

### Persistence Management

66

67

Control offline data persistence and cache behavior.

68

69

```typescript { .api }

70

/**

71

* Clear all cached data and pending writes

72

* @returns Promise resolving when persistence is cleared

73

*/

74

clearPersistence(): Promise<void>;

75

76

/**

77

* Wait for all pending writes to complete

78

* @returns Promise resolving when all writes are committed

79

*/

80

waitForPendingWrites(): Promise<void>;

81

82

/**

83

* Terminate the Firestore instance and clean up resources

84

* @returns Promise resolving when termination is complete

85

*/

86

terminate(): Promise<void>;

87

```

88

89

**Usage Examples:**

90

91

```typescript

92

import firestore from '@react-native-firebase/firestore';

93

94

// Clear all cached data (useful for user logout)

95

async function clearUserData() {

96

const db = firestore();

97

98

// First disable network to prevent new data

99

await db.disableNetwork();

100

101

// Clear all cached data

102

await db.clearPersistence();

103

104

console.log('All cached data cleared');

105

106

// Re-enable network for fresh start

107

await db.enableNetwork();

108

}

109

110

// Wait for pending writes before performing sensitive operations

111

async function performSecureOperation() {

112

const db = firestore();

113

114

// Ensure all pending writes are committed

115

await db.waitForPendingWrites();

116

console.log('All writes committed to server');

117

118

// Now safe to perform secure operation

119

await performSensitiveTask();

120

}

121

122

// Clean shutdown of Firestore

123

async function shutdownFirestore() {

124

const db = firestore();

125

126

// Wait for pending operations

127

await db.waitForPendingWrites();

128

129

// Terminate the instance

130

await db.terminate();

131

132

console.log('Firestore instance terminated');

133

}

134

135

// Handle app lifecycle for proper cleanup

136

class FirestoreManager {

137

async componentWillUnmount() {

138

try {

139

// Ensure data is persisted before app closes

140

await firestore().waitForPendingWrites();

141

} catch (error) {

142

console.error('Error waiting for writes:', error);

143

}

144

}

145

}

146

```

147

148

### Settings Configuration

149

150

Configure Firestore behavior including cache size, persistence, and server settings.

151

152

```typescript { .api }

153

/**

154

* Configure Firestore settings

155

* @param settings - Configuration options

156

* @returns Promise resolving when settings are applied

157

*/

158

settings(settings: FirebaseFirestoreTypes.Settings): Promise<void>;

159

160

interface Settings {

161

/**

162

* Enable or disable offline persistence

163

* @default true

164

*/

165

persistence?: boolean;

166

167

/**

168

* Cache size in bytes (-1 for unlimited)

169

* @default 104857600 (100 MB)

170

*/

171

cacheSizeBytes?: number;

172

173

/**

174

* Firestore host (for custom endpoints)

175

*/

176

host?: string;

177

178

/**

179

* Enable or disable SSL

180

* @default true

181

*/

182

ssl?: boolean;

183

184

/**

185

* Ignore undefined properties in document data

186

* @default false

187

*/

188

ignoreUndefinedProperties?: boolean;

189

190

/**

191

* Behavior for server timestamps that haven't been set yet

192

* @default 'none'

193

*/

194

serverTimestampBehavior?: 'estimate' | 'previous' | 'none';

195

}

196

```

197

198

**Usage Examples:**

199

200

```typescript

201

import firestore from '@react-native-firebase/firestore';

202

203

// Configure basic settings

204

await firestore().settings({

205

persistence: true,

206

cacheSizeBytes: 50 * 1024 * 1024, // 50 MB cache

207

ignoreUndefinedProperties: true

208

});

209

210

// Unlimited cache size

211

await firestore().settings({

212

cacheSizeBytes: firestore.CACHE_SIZE_UNLIMITED

213

});

214

215

// Custom server timestamp behavior

216

await firestore().settings({

217

serverTimestampBehavior: 'estimate' // Use local time estimate

218

});

219

220

// Development settings with custom host

221

await firestore().settings({

222

host: 'localhost:8080',

223

ssl: false,

224

persistence: false // Disable for development

225

});

226

227

// Production optimized settings

228

await firestore().settings({

229

persistence: true,

230

cacheSizeBytes: 100 * 1024 * 1024, // 100 MB

231

ignoreUndefinedProperties: true,

232

serverTimestampBehavior: 'estimate'

233

});

234

235

// Memory-constrained device settings

236

await firestore().settings({

237

persistence: true,

238

cacheSizeBytes: 10 * 1024 * 1024, // 10 MB cache

239

ignoreUndefinedProperties: true

240

});

241

```

242

243

### Emulator Support

244

245

Connect to the Firestore emulator for development and testing.

246

247

```typescript { .api }

248

/**

249

* Connect to Firestore emulator

250

* @param host - Emulator host

251

* @param port - Emulator port

252

* @returns Array containing actual host and port used (for testing)

253

*/

254

useEmulator(host: string, port: number): [string, number];

255

```

256

257

**Usage Examples:**

258

259

```typescript

260

import firestore from '@react-native-firebase/firestore';

261

262

// Connect to local emulator

263

if (__DEV__) {

264

// Connect to emulator running on localhost:8080

265

firestore().useEmulator('localhost', 8080);

266

console.log('Connected to Firestore emulator');

267

}

268

269

// Connect to emulator with custom configuration

270

if (__DEV__) {

271

const db = firestore();

272

273

// Use emulator

274

db.useEmulator('127.0.0.1', 8080);

275

276

// Configure for development

277

await db.settings({

278

persistence: false, // Disable persistence in development

279

cacheSizeBytes: 1024 * 1024 // 1 MB cache for testing

280

});

281

}

282

283

// Environment-based emulator configuration

284

const initializeFirestore = async () => {

285

const db = firestore();

286

287

if (process.env.NODE_ENV === 'development') {

288

// Development: use emulator

289

db.useEmulator('localhost', 8080);

290

291

await db.settings({

292

persistence: false,

293

ignoreUndefinedProperties: true

294

});

295

} else if (process.env.NODE_ENV === 'test') {

296

// Testing: use emulator with clean state

297

db.useEmulator('localhost', 8080);

298

299

await db.clearPersistence();

300

await db.settings({ persistence: false });

301

} else {

302

// Production: use real Firestore

303

await db.settings({

304

persistence: true,

305

cacheSizeBytes: 50 * 1024 * 1024,

306

ignoreUndefinedProperties: true

307

});

308

}

309

};

310

```

311

312

### Bundle Operations

313

314

Load pre-packaged data bundles for efficient initial data loading and execute pre-configured queries.

315

316

```typescript { .api }

317

/**

318

* Load a data bundle containing documents and queries

319

* @param bundle - Bundle data as string

320

* @returns Promise resolving to load bundle task progress

321

*/

322

loadBundle(bundle: string): Promise<FirebaseFirestoreTypes.LoadBundleTaskProgress>;

323

324

/**

325

* Get a pre-configured query from a loaded bundle

326

* @param queryName - Name of the query in the bundle

327

* @returns Query instance or null if not found

328

*/

329

namedQuery(queryName: string): FirebaseFirestoreTypes.Query | null;

330

331

interface LoadBundleTaskProgress {

332

/**

333

* Number of documents loaded so far

334

*/

335

documentsLoaded: number;

336

337

/**

338

* Total number of documents in the bundle

339

*/

340

totalDocuments: number;

341

342

/**

343

* Number of bytes loaded so far

344

*/

345

bytesLoaded: number;

346

347

/**

348

* Total number of bytes in the bundle

349

*/

350

totalBytes: number;

351

352

/**

353

* Current task state

354

*/

355

taskState: FirebaseFirestoreTypes.TaskState;

356

}

357

358

type TaskState = 'Error' | 'Running' | 'Success';

359

```

360

361

**Usage Examples:**

362

363

```typescript

364

import firestore from '@react-native-firebase/firestore';

365

366

// Load a data bundle

367

async function loadInitialData() {

368

const db = firestore();

369

370

try {

371

// Bundle data (typically fetched from server or included in app)

372

const bundleData = await fetch('/api/firestore-bundle').then(r => r.text());

373

374

// Load the bundle

375

const progress = await db.loadBundle(bundleData);

376

377

console.log('Bundle loaded successfully:');

378

console.log(`Documents: ${progress.documentsLoaded}/${progress.totalDocuments}`);

379

console.log(`Bytes: ${progress.bytesLoaded}/${progress.totalBytes}`);

380

console.log(`Status: ${progress.taskState}`);

381

382

// Use named queries from the bundle

383

const featuredProductsQuery = db.namedQuery('featured-products');

384

if (featuredProductsQuery) {

385

const snapshot = await featuredProductsQuery.get();

386

console.log(`Found ${snapshot.size} featured products`);

387

}

388

389

} catch (error) {

390

console.error('Error loading bundle:', error);

391

}

392

}

393

394

// Progressive bundle loading with progress tracking

395

async function loadBundleWithProgress(bundleData: string) {

396

const db = firestore();

397

398

// Note: In practice, you might want to implement progress tracking

399

// This is a simplified example showing the final result

400

const progress = await db.loadBundle(bundleData);

401

402

if (progress.taskState === 'Success') {

403

console.log('Bundle loaded successfully');

404

405

// Access bundled queries

406

const popularQuery = db.namedQuery('popular-items');

407

const recentQuery = db.namedQuery('recent-activity');

408

409

if (popularQuery && recentQuery) {

410

const [popularResults, recentResults] = await Promise.all([

411

popularQuery.get(),

412

recentQuery.get()

413

]);

414

415

console.log('Popular items:', popularResults.size);

416

console.log('Recent activity:', recentResults.size);

417

}

418

} else if (progress.taskState === 'Error') {

419

console.error('Bundle loading failed');

420

}

421

}

422

423

// Offline-first app initialization with bundles

424

async function initializeOfflineApp() {

425

const db = firestore();

426

427

// Load cached bundle for immediate offline access

428

try {

429

const cachedBundle = await getCachedBundle(); // Your caching logic

430

if (cachedBundle) {

431

await db.loadBundle(cachedBundle);

432

console.log('Offline bundle loaded');

433

}

434

} catch (error) {

435

console.log('No cached bundle available');

436

}

437

438

// Try to load fresh bundle when online

439

try {

440

const freshBundle = await fetchFreshBundle(); // Your fetch logic

441

if (freshBundle) {

442

await db.loadBundle(freshBundle);

443

console.log('Fresh bundle loaded');

444

await cacheBundleForOffline(freshBundle);

445

}

446

} catch (error) {

447

console.log('Could not load fresh bundle, using cached version');

448

}

449

}

450

```

451

452

### Cache Management

453

454

Access and manage persistent cache index operations.

455

456

```typescript { .api }

457

/**

458

* Get persistent cache index manager (null if persistence disabled)

459

* @returns PersistentCacheIndexManager instance or null

460

*/

461

persistentCacheIndexManager(): FirebaseFirestoreTypes.PersistentCacheIndexManager | null;

462

463

interface PersistentCacheIndexManager {

464

/**

465

* Enable automatic index creation for queries

466

* @returns Promise resolving when auto-creation is enabled

467

*/

468

enablePersistentCacheIndexAutoCreation(): Promise<void>;

469

470

/**

471

* Disable automatic index creation for queries

472

* @returns Promise resolving when auto-creation is disabled

473

*/

474

disablePersistentCacheIndexAutoCreation(): Promise<void>;

475

476

/**

477

* Delete all persistent cache indexes

478

* @returns Promise resolving when all indexes are deleted

479

*/

480

deleteAllPersistentCacheIndexes(): Promise<void>;

481

}

482

```

483

484

**Usage Examples:**

485

486

```typescript

487

import firestore from '@react-native-firebase/firestore';

488

489

// Manage cache indexes

490

async function manageCacheIndexes() {

491

const db = firestore();

492

const indexManager = db.persistentCacheIndexManager();

493

494

if (indexManager) {

495

// Enable automatic index creation

496

await indexManager.enablePersistentCacheIndexAutoCreation();

497

console.log('Auto index creation enabled');

498

499

// Later, if you need to clean up indexes

500

await indexManager.deleteAllPersistentCacheIndexes();

501

console.log('All cache indexes deleted');

502

503

// Disable auto creation

504

await indexManager.disablePersistentCacheIndexAutoCreation();

505

console.log('Auto index creation disabled');

506

} else {

507

console.log('Cache persistence is disabled - no index manager available');

508

}

509

}

510

511

// Initialize with index management

512

async function initializeWithCacheManagement() {

513

const db = firestore();

514

515

// Configure persistence

516

await db.settings({

517

persistence: true,

518

cacheSizeBytes: 100 * 1024 * 1024

519

});

520

521

// Manage indexes

522

const indexManager = db.persistentCacheIndexManager();

523

if (indexManager) {

524

await indexManager.enablePersistentCacheIndexAutoCreation();

525

}

526

}

527

```

528

529

### Offline Data Patterns

530

531

Best practices for working with offline data and handling connectivity changes.

532

533

**Usage Examples:**

534

535

```typescript

536

import firestore from '@react-native-firebase/firestore';

537

import NetInfo from '@react-native-netinfo/netinfo';

538

539

class OfflineManager {

540

private isOnline = true;

541

private pendingWrites: Array<() => Promise<void>> = [];

542

543

constructor() {

544

this.setupNetworkListener();

545

this.setupFirestoreSettings();

546

}

547

548

private async setupFirestoreSettings() {

549

await firestore().settings({

550

persistence: true,

551

cacheSizeBytes: 50 * 1024 * 1024,

552

ignoreUndefinedProperties: true,

553

serverTimestampBehavior: 'estimate'

554

});

555

}

556

557

private setupNetworkListener() {

558

NetInfo.addEventListener(state => {

559

const wasOnline = this.isOnline;

560

this.isOnline = state.isConnected ?? false;

561

562

if (!wasOnline && this.isOnline) {

563

this.handleConnectionRestored();

564

} else if (wasOnline && !this.isOnline) {

565

this.handleConnectionLost();

566

}

567

});

568

}

569

570

private async handleConnectionRestored() {

571

console.log('Connection restored - syncing data');

572

573

try {

574

// Enable network

575

await firestore().enableNetwork();

576

577

// Wait for pending writes to sync

578

await firestore().waitForPendingWrites();

579

580

console.log('All data synced successfully');

581

} catch (error) {

582

console.error('Error syncing data:', error);

583

}

584

}

585

586

private async handleConnectionLost() {

587

console.log('Connection lost - operating offline');

588

// Firestore automatically handles offline mode

589

// No need to explicitly disable network

590

}

591

592

// Queue writes for when connection is restored

593

async queueWrite(writeOperation: () => Promise<void>) {

594

if (this.isOnline) {

595

await writeOperation();

596

} else {

597

this.pendingWrites.push(writeOperation);

598

console.log('Write queued for when connection is restored');

599

}

600

}

601

602

// Get data with source preference

603

async getData(docRef: firestore.DocumentReference, preferCache = false) {

604

try {

605

if (preferCache || !this.isOnline) {

606

// Try cache first

607

const cacheSnapshot = await docRef.get({ source: 'cache' });

608

if (cacheSnapshot.exists) {

609

return cacheSnapshot;

610

}

611

}

612

613

// Fall back to server

614

return await docRef.get({ source: 'server' });

615

} catch (error) {

616

// If server fails, try cache

617

return await docRef.get({ source: 'cache' });

618

}

619

}

620

}

621

622

// Usage with real-time listeners that handle offline state

623

const setupOfflineAwareListener = (docRef: firestore.DocumentReference) => {

624

return docRef.onSnapshot(

625

{ includeMetadataChanges: true },

626

snapshot => {

627

if (snapshot.exists) {

628

const data = snapshot.data();

629

const isFromCache = snapshot.metadata.fromCache;

630

const hasPendingWrites = snapshot.metadata.hasPendingWrites;

631

632

console.log('Data:', data);

633

console.log('From cache:', isFromCache);

634

console.log('Has pending writes:', hasPendingWrites);

635

636

// Update UI with offline indicators

637

updateUI(data, { offline: isFromCache, pending: hasPendingWrites });

638

}

639

},

640

error => {

641

console.error('Listener error:', error);

642

// Handle offline errors gracefully

643

if (error.code === 'unavailable') {

644

console.log('Service unavailable - using cached data');

645

}

646

}

647

);

648

};

649

```

650

651

## Types

652

653

```typescript { .api }

654

/**

655

* Cache size constant for unlimited cache

656

*/

657

const CACHE_SIZE_UNLIMITED: -1;

658

659

/**

660

* Settings interface for Firestore configuration

661

*/

662

interface Settings {

663

persistence?: boolean;

664

cacheSizeBytes?: number;

665

host?: string;

666

ssl?: boolean;

667

ignoreUndefinedProperties?: boolean;

668

serverTimestampBehavior?: 'estimate' | 'previous' | 'none';

669

}

670

671

/**

672

* Get options for specifying data source

673

*/

674

interface GetOptions {

675

source: 'default' | 'server' | 'cache';

676

}

677

678

/**

679

* Persistent cache index manager for query optimization

680

*/

681

interface PersistentCacheIndexManager {

682

enablePersistentCacheIndexAutoCreation(): Promise<void>;

683

disablePersistentCacheIndexAutoCreation(): Promise<void>;

684

deleteAllPersistentCacheIndexes(): Promise<void>;

685

}

686

```