wrap
`HotUpdater.wrap` checks for updates at the entry point, and if there is a bundle to update, it downloads the bundle and applies the update strategy.
Usage
Important:
HotUpdater.wrapis required for all apps. It enables automatic crash detection and rollback. All HotUpdater methods will throw an error if wrap is not used.
HotUpdater.wrap supports two usage patterns:
Option 1: With Automatic Updates
Use this for apps that want automatic OTA updates. This is the standard approach with full update management.
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateStrategy: "appVersion", // or "fingerprint"
updateMode: "auto",
// If you need to send request headers, you can use the `requestHeaders` option.
requestHeaders: {
"Authorization": "Bearer <your-access-token>",
},
})(App);Option 2: Manual Updates Only (Custom Flow)
Use this for apps with custom update logic.
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateMode: "manual",
})(App);Then use checkForUpdate or updateBundle manually when needed:
import { HotUpdater } from "@hot-updater/react-native";
import { useEffect } from "react";
function App() {
useEffect(() => {
const checkUpdate = async () => {
const updateInfo = await HotUpdater.checkForUpdate({
updateStrategy: "appVersion", // Required: specify update strategy
requestHeaders: {
Authorization: "Bearer <your-access-token>",
},
});
if (!updateInfo) {
console.log("No update found");
return;
}
await updateInfo.updateBundle();
if (updateInfo.shouldForceUpdate) {
await HotUpdater.reload();
}
};
checkUpdate();
}, []);
// ... your app
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateMode: "manual",
requestHeaders: {
"Authorization": "Bearer <your-access-token>",
},
})(App);Configuration Reference
HotUpdater.wrap accepts different options depending on the update mode.
Common Options
Available in both automatic and manual modes:
| Option | Type | Required | Description |
|---|---|---|---|
baseURL | string | Yes* | Your update server URL (standard approach) |
resolver | HotUpdaterResolver | Yes* | Custom network operations (advanced) |
requestHeaders | Record<string, string> | No | Custom HTTP headers for update requests |
requestTimeout | number | No | Request timeout in milliseconds (default: 5000) |
*Either baseURL or resolver must be provided (mutually exclusive)
Automatic Mode Options
The following options are only available when updateMode: "auto" or omitted (automatic mode is the default):
| Option | Type | Required | Description |
|---|---|---|---|
updateStrategy | "appVersion" | "fingerprint" | Yes | Update detection strategy |
requestHeaders | Record<string, string> | No | Custom HTTP headers for update requests |
requestTimeout | number | No | Request timeout in milliseconds (default: 5000) |
fallbackComponent | React.FC<{status, progress, message}> | No | UI component shown during updates |
onProgress | (progress: number) => void | No | Callback fired during bundle download (0-1) |
reloadOnForceUpdate | boolean | No | Auto-reload on force updates (default: true) |
onUpdateProcessCompleted | (response) => void | No | Callback when update process completes |
onError | (error) => void | No | Error handler for update failures |
fallbackComponent
During an update check, access to the entry point is temporarily blocked while communicating with the server.
- If the update is force update, the entry point remains blocked, and the progress updates as the bundle downloads.
- If not force update, the entry point is only blocked during the update check.
Without a fallbackComponent, 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: Optional message from the server
Example:
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text, Modal } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateStrategy: "appVersion", // or "fingerprint"
updateMode: "auto",
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 a force update bundle is downloaded, the app will automatically reload. If false, shouldForceUpdate will be returned as true in onUpdateProcessCompleted but the app won't reload. Default is true.
Example with auto-reload:
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateStrategy: "appVersion", // or "fingerprint"
updateMode: "auto",
// If you need to send request headers, you can use the `requestHeaders` option.
requestHeaders: {
"Authorization": "Bearer <your-access-token>",
},
reloadOnForceUpdate: true, // Automatically reload the app on force updates
})(App);Example without auto-reload:
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateStrategy: "appVersion", // or "fingerprint"
updateMode: "auto",
// If you need to send request headers, you can use the `requestHeaders` option.
requestHeaders: {
"Authorization": "Bearer <your-access-token>",
},
reloadOnForceUpdate: false, // The app won't reload on force updates
onUpdateProcessCompleted: ({ status, shouldForceUpdate, id, message }) => {
console.log("Bundle updated:", status, shouldForceUpdate, id, message);
if (shouldForceUpdate) {
await HotUpdater.reload();
}
},
})(App);onUpdateProcessCompleted
Allows you to perform additional actions after the update process is completed.
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 ID of the bundle to update |
message | string | The message of the update process |
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateStrategy: "appVersion", // or "fingerprint"
updateMode: "auto",
// If you need to send request headers, you can use the `requestHeaders` option.
requestHeaders: {
"Authorization": "Bearer <your-access-token>",
},
onUpdateProcessCompleted: ({ status, shouldForceUpdate, id, message }) => {
console.log("Bundle updated:", status, shouldForceUpdate, id, message);
},
// If you need to show the progress while downloading the new bundle, you can use the `onProgress` option.
onProgress: (progress) => {
console.log("Bundle downloading progress:", progress);
},
})(App);onError
Handles all errors during the update process.
Example:
import { HotUpdater } from "@hot-updater/react-native";
import { Alert } from "react-native";
export default HotUpdater.wrap({
baseURL: "<your-update-server-url>",
updateStrategy: "appVersion",
updateMode: "auto",
onError: (error) => {
// Handle other errors
console.error("Update error:", error);
},
})(App);How It Works
When you use HotUpdater.wrap with automatic updates, it constructs the appropriate endpoint URL based on the updateStrategy:
- For
updateStrategy: "appVersion":GET {baseURL}/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId - For
updateStrategy: "fingerprint":GET {baseURL}/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId
The function automatically appends the correct path and parameters to your baseURL.
Advanced: Custom Resolver
For advanced use cases where you need full control over network operations - such as implementing a custom server, using GraphQL, or complex authentication flows - you can use a custom resolver instead of baseURL.
import { HotUpdater } from "@hot-updater/react-native";
import { useEffect } from "react";
function App() {
useEffect(() => {
const checkUpdate = async () => {
// When you call HotUpdater.checkForUpdate(),
// it will use the resolver.checkUpdate() defined below
const updateInfo = await HotUpdater.checkForUpdate({
updateStrategy: "appVersion",
});
if (updateInfo) {
await updateInfo.updateBundle();
if (updateInfo.shouldForceUpdate) {
await HotUpdater.reload();
}
}
};
checkUpdate();
}, []);
return ...
}
export default HotUpdater.wrap({
resolver: {
// Override the default update check logic
checkUpdate: async (params) => {
// Custom network logic - GraphQL, custom API, etc.
const response = await fetch(`https://custom-api.com/check`, {
method: 'POST',
body: JSON.stringify({
platform: params.platform,
appVersion: params.appVersion,
bundleId: params.bundleId,
}),
headers: params.requestHeaders,
});
if (!response.ok) return null;
return response.json();
},
},
updateMode: "manual", // or "auto"
})(App);Note: The
resolveroption is mutually exclusive withbaseURL. Usingresolver.checkUpdate()overrides the default update check implementation.
Flag Behavior
| Update Type | When Applied | How to Enable |
|---|---|---|
| Default | Downloads the update bundle in the background and applies it when the user restarts the app. | Default setting |
| Force Update | Downloads the update bundle and applies it immediately. | Use the --force-update flag or console. |