wrap
`hotUpdater.wrap` checks for an update when the app's root mounts, stages standard updates for the next start, and reloads forced updates by default.
Usage
wrap is a method of the instance HotUpdater.init
returns. Wrap the app's root with it, and it checks for an update when the root
mounts. The update server, request headers, plugins, and onError come from
HotUpdater.init; wrap takes only the update flow.
import { Text, View } from "react-native";
import { hotUpdater } from "./src/hotUpdater";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default App;
export default hotUpdater.wrap({
updateStrategy: "appVersion", // or "fingerprint"
})(App);src/hotUpdater.ts is the module that calls HotUpdater.init and exports the
instance, as init
shows.
A standard update is prepared and staged without reloading the React Native
runtime currently in use. It becomes active the next time that runtime starts,
normally on the next cold app launch. An update with shouldForceUpdate: true,
including a bundle-changing server-directed rollback, is prepared and then
reloads the app by default. Set reloadOnForceUpdate: false when the current
session must remain uninterrupted.
To choose when the app checks, call
hotUpdater.checkForUpdate() from
your own flow instead, as the custom update guide
shows. Use one of the two for a launch, so the app does not check twice.
Configuration reference
| Option | Type | Required | Description |
|---|---|---|---|
updateStrategy | "appVersion" | "fingerprint" | Yes | Update detection strategy |
fallbackComponent | React.FC<HotUpdaterFallbackComponentProps> | No | UI shown instead of the root during a check and a forced update |
onProgress | (progress: number) => void | No | Callback fired during bundle download (0-1) |
reloadOnForceUpdate | boolean | No | Reload after a forced update is prepared (default: true) |
onUpdateProcessCompleted | (response) => void | No | Callback when the update process completes |
Errors during the flow go to the onError handler of HotUpdater.init.
fallbackComponent
While the update check runs, the fallback replaces the app's root.
- For a forced update, the fallback stays until the bundle is downloaded, and progress updates as it downloads.
- For a standard update, the fallback shows only during the update check.
Without a fallbackComponent, the root renders at once and the bundle
downloads without blocking the screen.
Props:
progress: Download progress (0-1, e.g., for a progress bar)status: Update state (CHECK_FOR_UPDATEorUPDATING)message: Message from the server, ornullartifactType:"diff"ornullbefore progress startsdetails: Per-file diff progress, ornull
The progress fields have the same shape as
useHotUpdaterStore.
import { Text, View } from "react-native";
import { hotUpdater } from "./src/hotUpdater";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default hotUpdater.wrap({
updateStrategy: "appVersion",
fallbackComponent: ({ progress, status, message }) => (
<View
style={{
flex: 1,
padding: 20,
borderRadius: 10,
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0, 0, 0, 0.5)",
}}
>
{/* You can put a splash image here. */}
<Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
{status === "UPDATING" ? "Updating..." : "Checking for Update..."}
</Text>
{message && (
<Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
{message}
</Text>
)}
{progress > 0 ? (
<Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
{Math.round(progress * 100)}%
</Text>
) : null}
</View>
),
})(App);reloadOnForceUpdate
When wrap receives an update with shouldForceUpdate: true, it prepares the
selected transition and reloads the app, after HotUpdater.init has read the
current launch. Bundle-changing server-directed rollbacks also use this path.
If set to false, the current React Native runtime keeps running and the staged
update becomes active on the next runtime start or after a later
hotUpdater.reload() call.
This option only controls wrap. updateBundle() never reloads the app by
itself. The reload follows
hotUpdater.setReloadBehavior().
export default hotUpdater.wrap({
updateStrategy: "appVersion",
reloadOnForceUpdate: false, // Keep the current session running
})(App);onUpdateProcessCompleted
Reports when wrap has finished handling the update.
For a standard update, wrap invokes this callback after starting the
non-blocking download, not after the download finishes. Do not use it as a
download-readiness signal.
UP_TO_DATE means the check returned no transition. A failed check can also
return null after calling init.onError, so this status alone does not prove
that the server was reached or the app is current.
Callback arguments:
| Property | Type | Description |
|---|---|---|
status | "ROLLBACK" | "UPDATE" | "UP_TO_DATE" | The status of the update process |
shouldForceUpdate | boolean | Whether the update process is forced |
id | string | The selected update's console ID |
message | string | null | The message of the update process |
export default hotUpdater.wrap({
updateStrategy: "appVersion",
onUpdateProcessCompleted: ({ status, shouldForceUpdate, id, message }) => {
console.log("Update process completed:", status, shouldForceUpdate, id, message);
},
onProgress: (progress) => {
console.log("Bundle download progress:", progress);
},
})(App);How it works
The client reads a shared Release Catalog, selects a transition on the device, and resolves the artifact when staging is needed. See how updates work for the full lifecycle.
Flag behavior
| Update Response | Runtime Behavior | How to Enable |
|---|---|---|
shouldForceUpdate: false | Stages the selected bundle without reloading the current runtime; it becomes active on the next runtime start. | Default setting |
shouldForceUpdate: true | wrap reloads after preparing the selected transition; reloadOnForceUpdate: false defers it to a later start. | Use --force-update or the console; bundle-changing rollbacks also return it. |