useBundleDrop
What useBundleDrop Is
useBundleDrop is the React hook for interacting with the initialized Bundle Drop runtime.
It gives you state plus explicit actions so you can build your own update UI, such as a "Check for updates" button, a download button, or a custom update prompt.
When to Use It
Use useBundleDrop when you want the app to decide how and when update actions happen from React UI.
This is the better fit when:
- users trigger update checks manually
- you want custom buttons, prompts, or settings screens
- you want to switch channels from your own UI
Call BundleDrop.init first, then use the hook inside your screens or components.
Hook Options
useBundleDrop() takes no arguments.
The active channel comes from the runtime started by BundleDrop.init and can be changed later with setChannel(...).
What It Returns
status: latest human-readable status messageisEnabled: whether Bundle Drop is active for the current runtimeisBusy: whether an update action is currently runningchannelName: active runtime channel used by OTA actionssetChannel(channelName): changes the active runtime channelinstalledInfo: metadata for the installed bundle, if presentpendingApply: whether a downloaded bundle is waiting to be appliedhasBundle: whether a downloaded bundle exists locallycheckLatest(): checks for update availabilitydownloadUpdate(): downloads and stages an updateapplyUpdate(): applies a staged updatefetchAvailableChannels(): fetches public channel names for the projectavailableChannels: last fetched channel listfetchBundles(options?): fetches a paginated list of downloadable bundles for a channelinstallBundle(bundleListItem): downloads and stages a specific bundle from the list
Action Return Shapes
checkLatest() returns:
Promise<{
response:
| {
action: "NOOP" | "INSTALL" | "ROLLBACK";
upToDate?: boolean;
bundleVersion?: number;
version?: string;
hash?: string;
downloadUrl?: string;
channelName?: string;
reason?: string;
incompatible?: boolean;
runtimeVersion?: string;
requestedRuntimeVersion?: string;
latestRuntimeVersionOnChannel?: string;
}
| null;
status?: string;
}>
downloadUpdate() returns:
Promise<{
result:
| { status: "staged"; bundlePath: string; hash: string }
| { status: "upToDate" }
| { status: "disabled" }
| { status: "incompatible" }
| { status: "rollback"; reason?: string };
status?: string;
}>
applyUpdate() returns:
Promise<{
result:
| { status: "applied" }
| { status: "noBundle" }
| { status: "disabled" }
| { status: "alreadyApplied" };
status?: string;
}>
fetchBundles(options?) returns:
Promise<{
items: BundleListItem[];
nextCursor: string | null;
hasMore: boolean;
}>
Each BundleListItem contains hash, bundleVersion, version, platform, runtimeVersion, releaseNotes, createdAt, and downloadUrl.
Options: channelName, platform, limit (1–50), cursor.
installBundle(bundleListItem) returns:
Promise<{
result:
| { status: "staged"; bundlePath: string; hash: string }
| { status: "upToDate" }
| { status: "disabled" }
| { status: "incompatible" }
| { status: "rollback"; reason?: string };
status?: string;
}>
Typical Usage
1const {
2 status,
3 channelName,
4 setChannel,
5 isBusy,
6 installedInfo,
7 pendingApply,
8 checkLatest,
9 downloadUpdate,
10 applyUpdate,
11} = useBundleDrop();
12
13setChannel("Beta");
14
15// Example flow:
16// 1. User taps "Check for updates"
17// 2. User taps "Download"
18// 3. User taps "Apply now" or waits for next launchBundle Browsing Usage
1const {
2 channelName,
3 setChannel,
4 isBusy,
5 status,
6 fetchBundles,
7 installBundle,
8 applyUpdate,
9} = useBundleDrop();
10
11setChannel("production");
12
13// Fetch available bundles
14const page = await fetchBundles({ limit: 10 });
15// page.items = [{ hash, bundleVersion, version, releaseNotes, ... }]
16
17// Load more
18const nextPage = await fetchBundles({ cursor: page.nextCursor });
19
20// User picks a version from the list
21const result = await installBundle(page.items[2]);
22if (result.result.status === "staged") {
23 await applyUpdate(); // reload with the selected version
24}Bundle Drop handles the download, staging, and installation. Your app only needs to render the list and handle user selection.
How It Differs from BundleDrop.init
The difference is mostly about control:
- BundleDrop.init is the required startup controller
useBundleDropis the React helper for manual, UI-driven behavior on top of that runtime
You can still use the same underlying Bundle Drop integration either way. The difference is whether the app handles updates automatically at startup or exposes that flow through your own interface.
Best Fit
useBundleDrop is best for:
- custom update screens
- settings-based update controls
- apps that want explicit user interaction around updates
Related Docs
- For lower-level functions and their raw return shapes, see Runtime APIs.
- For runtime startup setup, see BundleDrop.init.
- For policy behavior, see Update Policies.
- For SDK overview, see SDK Integration.