API Guide
Understand the status model, helper functions, update flows, and errors.
Capability-First Design
Capability-first means checking what the current install can do before starting an update flow. Instead of checking if (Platform.OS === 'android'), you check what the current environment supports:
import { getUpdateStatus } from '@rnforge/react-native-in-app-updates';
const status = await getUpdateStatus();
if (status.capabilities.immediate) {
// Immediate updates are supported
}
if (status.capabilities.flexible) {
// Flexible updates are supported
}This approach works because:
- iOS reports immediate and flexible update capabilities as
false - iOS can still report store-page and version-lookup capability when App Store options are provided
- Android installs that cannot run Play update flows report those flow capabilities as
false - Android Play installs report the update capabilities allowed by Play Core
- Your code works everywhere without platform checks
Typed Results, Not Exceptions
Expected states are returned as typed results, not thrown exceptions:
const status = await getUpdateStatus();
// Check if updates are supported
if (!status.supported) {
console.log('Reason:', status.reason);
// 'unsupported-platform' | 'unsupported-install-source' | etc.
} else if (status.updateAvailable) {
console.log('Current:', status.currentVersion);
console.log('Latest:', status.latestStoreVersion);
}Exceptions are only thrown for actual errors:
- Invalid input (e.g., missing required options)
- Native bridge failures
- Native layer failures
- Unexpected runtime errors
Update Status
The UpdateStatus object is the core of the API. It tells you:
Prop
Type
Platform Support
status.supported // boolean - are in-app updates supported?
status.reason // string - why or why not
status.platform // 'android' | 'ios'Update Availability
status.updateAvailable // boolean | null
status.currentVersion // string - installed version
status.latestStoreVersion // string - latest in store
status.currentBuild // string | number - installed build
status.latestStoreBuild // string | number - latest build in storeCapabilities
Prop
Type
status.capabilities.immediate // boolean
status.capabilities.flexible // boolean
status.capabilities.storePage // boolean
status.capabilities.latestVersionLookup // boolean
status.capabilities.installStateListener // booleanAllowed Flows
Even if a capability is supported, it might not be allowed right now:
Prop
Type
status.allowed.immediate // boolean - can start immediate update now?
status.allowed.flexible // boolean - can start flexible update now?Install Status
For flexible updates, track the installation lifecycle:
status.installStatus
// 'unknown' | 'pending' | 'downloading' | 'downloaded' |
// 'installing' | 'installed' | 'failed' | 'canceled' | 'unsupported'Platform-Specific Details
// Android details (only on Android)
status.android?.packageName
status.android?.playCore?.availableVersionCode
status.android?.playCore?.updatePriority
// iOS details (only on iOS)
status.ios?.bundleIdentifier
status.ios?.appStoreId
status.ios?.appStore?.version
status.ios?.appStore?.releaseNotesImmediate Updates
Immediate updates show a blocking UI that forces the user to update before continuing:
import {
getUpdateStatus,
startImmediateUpdate,
canStartImmediateUpdate
} from '@rnforge/react-native-in-app-updates';
const status = await getUpdateStatus();
if (canStartImmediateUpdate(status)) {
try {
const result = await startImmediateUpdate();
// Update completed or app restarted
} catch (error) {
// Handle error (invalid-input, bridge-error, native-error, unexpected)
console.error('Update failed:', error);
}
}When to use immediate updates:
- Critical security fixes
- Breaking API changes
- Mandatory feature updates
Flexible Updates
Flexible updates download in the background while the user continues using the app:
Prop
Type
import {
getUpdateStatus,
startFlexibleUpdate,
completeFlexibleUpdate,
addInstallStateListener,
canStartFlexibleUpdate,
} from '@rnforge/react-native-in-app-updates';
const status = await getUpdateStatus();
if (canStartFlexibleUpdate(status)) {
let subscription: { remove: () => void } | undefined;
subscription = addInstallStateListener((event) => {
if (event.installStatus === 'downloading') {
const progress = event.progress ?? 0;
console.log(`Downloaded: ${(progress * 100).toFixed(1)}%`);
}
if (event.installStatus === 'downloaded') {
console.log('Update downloaded, installing');
void completeFlexibleUpdate().finally(() => {
subscription?.remove();
});
}
});
try {
const result = await startFlexibleUpdate();
console.log('Flexible update result:', result.reason);
} catch (error) {
subscription?.remove();
throw error;
}
}When to use flexible updates:
- Non-critical feature updates
- Performance improvements
- UI enhancements
- When you want to avoid interrupting the user
Store Page Fallback
If in-app updates aren't supported, you can still open the store page:
import { openStorePage, canOpenStorePage, getUpdateStatus } from '@rnforge/react-native-in-app-updates';
const storeOptions = {
ios: {
appStoreId: '123456789',
country: 'us',
},
};
const status = await getUpdateStatus(storeOptions);
if (canOpenStorePage(status)) {
try {
await openStorePage(storeOptions);
// Opens Play Store on Android or App Store on iOS.
} catch (error) {
console.error('Failed to open store:', error);
}
}On Android, openStorePage() can be called without options. On iOS, pass ios.appStoreId to both getUpdateStatus() and openStorePage() so the status result can report the store-page capability correctly.
Error Handling
Async functions that call the native module can throw InAppUpdatesError. Helper functions only read an UpdateStatus object.
| Code | Meaning |
|---|---|
invalid-input | Invalid options or arguments. |
bridge-error | React Native bridge communication failed. |
native-error | Native layer reported a failure. |
unexpected | Any other unexpected failure. |
import { InAppUpdatesError } from '@rnforge/react-native-in-app-updates';
try {
await startImmediateUpdate();
} catch (error) {
if (error instanceof InAppUpdatesError) {
switch (error.code) {
case 'invalid-input':
// You passed invalid options
console.error('Invalid input:', error.message);
break;
case 'bridge-error':
// React Native bridge communication failed
console.error('Bridge error:', error.message);
break;
case 'native-error':
// Native layer reported an error
console.error('Native error:', error.message);
if (error.android) {
console.error('Android details:', error.android);
}
break;
case 'unexpected':
// Something unexpected happened
console.error('Unexpected error:', error.message);
break;
}
} else {
// Not an InAppUpdatesError
throw error;
}
}Helper Functions
The API provides helper functions to check status before acting:
import {
getUpdateStatus,
isUpdateAvailable,
canStartImmediateUpdate,
canStartFlexibleUpdate,
canCompleteFlexibleUpdate,
canOpenStorePage,
supportsInstallStateListener,
} from '@rnforge/react-native-in-app-updates';
const status = await getUpdateStatus();
if (isUpdateAvailable(status)) {
console.log('Update available');
}
if (canStartImmediateUpdate(status)) {
console.log('Can start immediate update');
}
if (canStartFlexibleUpdate(status)) {
console.log('Can start flexible update');
}
if (canCompleteFlexibleUpdate(status)) {
console.log('Can complete flexible update');
}
if (canOpenStorePage(status)) {
console.log('Can open store page');
}
if (supportsInstallStateListener(status)) {
console.log('Install state listener is supported');
}These helpers check multiple conditions (support, capability, availability, allowed) so you don't have to.
Platform Notes
Android
- Requires Google Play Store (sideloaded apps report
unsupported-install-source) - Requires Google Play Services (devices without report
play-core-unavailable) - APK expansion files are not supported (
apk-expansion-files-unsupported) - Immediate updates may not be allowed during certain app states
- Flexible updates require calling
completeFlexibleUpdate()to install
iOS
- Immediate and flexible update flows are not supported
- Store page opening requires
ios.appStoreId - Version lookup uses the App Store lookup API when
ios.appStoreIdis provided getUpdateStatus()can returnmissing-app-store-idwhen App Store lookup options are missing- Use
openStorePage()as the update mechanism
Common Patterns
Check for Update on App Start
import { getUpdateStatus, isUpdateAvailable } from '@rnforge/react-native-in-app-updates';
async function checkForUpdate() {
const status = await getUpdateStatus();
if (!status.supported) {
console.log('Updates not supported:', status.reason);
return null;
}
if (!isUpdateAvailable(status)) {
console.log('App is up to date');
return null;
}
return {
current: status.currentVersion,
latest: status.latestStoreVersion,
releaseNotes: status.ios?.appStore?.releaseNotes,
};
}Progressive Update Flow
A common pattern is to try immediate updates first for critical updates, fall back to flexible for non-critical updates, and use the store page as a last resort. See App Integration for a full React component that implements this fallback chain.
Next Steps
- Check the Quick Start for a minimal example
- Review the Installation guide for setup instructions
- See App Integration for a full React component example
- See Troubleshooting for common issues and fixes