Checking For and Applying Updates
Call the OTA Update SDK from your React Native app: check for updates, show progress, and control when a new bundle is applied.
For most apps this is the entire integration — one import, one wrapper:
import { withOtaUpdate } from '@otaupdate/react-native';
function App() {
return <YourApp />;
}
export default withOtaUpdate(App);That gives you, with no further code:
- a check on app launch and on every return to the foreground (at most one per minute);
- a background download, with the SHA-256 verified natively before anything is unzipped;
- installation on the next cold start, so a user is never interrupted;
notifyAppReady()on mount — which is what arms rollback protection.
notifyAppReady() is not optional
notifyAppReady() before the next launch, the native layer assumes the update is broken, reverts to the previous bundle and blacklists the bad hash. withOtaUpdate and startAutoSync call it for you. If you wire things up by hand, you must call it yourself — after your critical startup path, but not so late that a user can sit on a broken screen without it firing.Tuning the automatic behaviour
Pass options to change when it checks and how it installs:
import { withOtaUpdate, InstallMode } from '@otaupdate/react-native';
export default withOtaUpdate(App, {
checkOnAppStart: true, // default
checkOnResume: true, // default
minimumSyncInterval: 60, // seconds between automatic syncs; default 60
sync: {
installMode: InstallMode.ON_NEXT_RESTART, // default
mandatoryInstallMode: InstallMode.IMMEDIATE, // default for mandatory releases
},
});Not using the HOC — a non-React entry point, or your own bootstrap sequence? Call startAutoSync directly; it takes the same options and returns a teardown function.
import { startAutoSync, InstallMode } from '@otaupdate/react-native';
const stop = startAutoSync({ sync: { installMode: InstallMode.ON_NEXT_RESUME } });Manual control
sync() is check → download → install in one call. It is safe to call whenever you like: concurrent calls share the run in flight rather than downloading twice, and it resolves with a SyncStatus instead of throwing.
import OtaUpdate, { InstallMode, SyncStatus } from '@otaupdate/react-native';
const status = await OtaUpdate.sync({
installMode: InstallMode.ON_NEXT_RESTART,
mandatoryInstallMode: InstallMode.IMMEDIATE,
onSyncStatusChange: (s) => console.log(SyncStatus[s]),
onDownloadProgress: ({ receivedBytes, totalBytes }) =>
console.log(Math.round((receivedBytes / totalBytes) * 100) + '%'),
// Ask the user first. Mandatory releases ignore the answer.
shouldInstall: (update) => confirmWithUser(update.description),
});
if (status === SyncStatus.UPDATE_INSTALLED) {
// Applied on the next restart — or call restartApp(true) to apply it now.
}Update UI with the hook
useOtaUpdate exposes the same machinery as React state, for a "new version available" banner or a manual Check for updates button in settings.
import { useEffect } from 'react';
import { Button, Text, View } from 'react-native';
import { useOtaUpdate } from '@otaupdate/react-native';
export function UpdateBanner() {
const { available, progress, isSyncing, check, update } = useOtaUpdate();
useEffect(() => { void check(); }, [check]);
if (!available) return null;
return (
<View>
<Text>Version {available.label} is available</Text>
{progress && <Text>{Math.round((progress.receivedBytes / progress.totalBytes) * 100)}%</Text>}
<Button title="Update" onPress={() => update()} disabled={isSyncing} />
</View>
);
}Building your own UI this way does not replace rollback protection — keep withOtaUpdate (or your own notifyAppReady() call) at the root.
Showing the running version
import { getCurrentPackage } from '@otaupdate/react-native';
const pkg = await getCurrentPackage();
// null when the app is running the bundle shipped in the binary.
// Otherwise: { label: '#12', packageHash, isPending, isFirstRun, appVersion, … }