HotUpdater.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

Use the source option in HotUpdater.wrap to specify the update server URL, then wrap the App entry point.

Since it uses fetch, if you need to pass headers along with it, you can use the requestHeaders option to pass headers.

import { HotUpdater, getUpdateSource } from "@hot-updater/react-native";
import { View, Text } from "react-native";

function App() {
  return (
    <View>
      <Text>Hello World</Text>
    </View>
  );
}

export default HotUpdater.wrap({ 
  source: getUpdateSource("<your-update-server-url>", {
    updateStrategy: "fingerprint", // or "appVersion"
  }),
  // If you need to send request headers, you can use the `requestHeaders` option.
  requestHeaders: {
    "Authorization": "Bearer <your-access-token>",
  },
})(App);

UnderstandinggetUpdateSource

The getUpdateSource function is used to construct the final URL for checking for updates. It takes a baseUrl as its first argument and an options object as its second argument. The updateStrategy property within the options object determines the final structure of the request URL.

Example Final Endpoint Structures:

Depending on the updateStrategy value, getUpdateSource generates URLs like the following:

  • For updateStrategy: 'appVersion': GET {baseUrl}/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId
  • For updateStrategy: 'fingerprint': GET {baseUrl}/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId

For example, if you provide https://your-update-server.com/api/update-check as the baseUrl, getUpdateSource will append the correct path and parameters to the URL depending on whether updateStrategy is 'appVersion' or 'fingerprint'.

Fallback Component

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.

fallbackComponent Props:

  • progress: Download progress (e.g., for a progress bar).
  • status: Update state:
    • CHECK_FOR_UPDATE: Checking for updates.
    • UPDATING: Downloading the new bundle.

Using these props, you can ensure a smooth UI transition.
It is also recommended to include a splash image for a better user experience.

import { HotUpdater, getUpdateSource } 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({ 
  source: getUpdateSource("<your-update-server-url>", {
    updateStrategy: "fingerprint", // or "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 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.

reloadOnForceUpdate istrue

When a force update exists, the app will automatically reload.

import { HotUpdater, getUpdateSource } from "@hot-updater/react-native";
import { View, Text } from "react-native";

function App() {
  return (
    <View>
      <Text>Hello World</Text>
    </View>
  );
}

export default HotUpdater.wrap({
  source: getUpdateSource("<your-update-server-url>", {
    updateStrategy: "fingerprint", // or "appVersion"
  }),
  // 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);

reloadOnForceUpdate isfalse

When a force update exists, the app will not reload. shouldForceUpdate will be returned as true in onUpdateProcessCompleted.

import { HotUpdater, getUpdateSource } from "@hot-updater/react-native";
import { View, Text } from "react-native";

function App() {
  return (
    <View>
      <Text>Hello World</Text>
    </View>
  );
}

export default HotUpdater.wrap({
  source: getUpdateSource("<your-update-server-url>", {
    updateStrategy: "fingerprint", // or "appVersion"
  }),
  // 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) { 
      HotUpdater.reload(); 
    } 
  },
})(App);

onUpdateProcessCompleted

The onUpdateProcessCompleted option allows you to perform additional actions after the update process is completed.

Callback Arguments

PropertyTypeDescription
status"ROLLBACK" | "UPDATE" | "UP_TO_DATE"The status of the update process
shouldForceUpdatebooleanWhether the update process is forced
idstringThe ID of the bundle to update
messagestringThe message of the update process
import { HotUpdater, getUpdateSource } from "@hot-updater/react-native";
import { View, Text } from "react-native";

function App() {
  return (
    <View>
      <Text>Hello World</Text>
    </View>
  );
}

export default HotUpdater.wrap({
  source: getUpdateSource("<your-update-server-url>", {
    updateStrategy: "fingerprint", // or "appVersion"
  }),
  // If you need to send request headers, you can use the `requestHeaders` option.
  requestHeaders: {
    "Authorization": "Bearer <your-access-token>",
  },
  onUpdateProcessCompleted: ({ isBundleUpdated, message }) => {
    // if isBundleUpdated is true, `HotUpdater.reload()` or restart the app to apply the new bundle
    // if isBundleUpdated is false, the app is up to date
    console.log("Bundle updated:", isBundleUpdated, 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);

Update Strategy

Update TypeWhen AppliedHow to Enable
DefaultDownloads the update bundle in the background and applies it when the user restarts the app.Default setting
Force UpdateDownloads the update bundle and applies it immediately.Use the --force-update flag or console.

Custom source Function

You can pass an async function to the source option for full control over how update info is fetched.

export default HotUpdater.wrap({
  source: async () => {
    const res = await fetch("https://your.api/update-info");
    return (await res.json()) as AppUpdateInfo | null;
  },
  // ... other options
});