Teardown

Force Updates

Require, recommend, or block app versions with the useForceUpdate hook.

The SDK checks the running version against your dashboard rules on launch (and when the app returns to the foreground). Your UI reacts to a single hook, useForceUpdate().

Version statuses

useForceUpdate() returns booleans for the common cases, plus the raw versionStatus and any releaseNotes.

StatusMeaningWhat you should do
up_to_dateRunning an allowed versionNothing
update_availableA newer version existsOptional nudge
update_recommendedUpdate is encouragedDismissible banner
update_requiredVersion is blockedHard gate — block the app
checking / initializingStill resolvingShow nothing or a splash
disabledChecks are turned offNothing
const {
  isUpdateAvailable,   // available, recommended, or required
  isUpdateRecommended, // recommended only
  isUpdateRequired,    // blockedmust update
  releaseNotes,        // string | null
  versionStatus,       // the raw discriminated union
} = useForceUpdate();

Required: full-screen gate

Block the app entirely until the user updates. Wrap your navigator with this.

UpdateGate.tsx
import { useForceUpdate } from "@teardown/force-updates";
import { Linking, Text, TouchableOpacity, View } from "react-native";

export function UpdateGate({ children }: { children: React.ReactNode }) {
  const { isUpdateRequired, releaseNotes } = useForceUpdate();

  if (!isUpdateRequired) return <>{children}</>;

  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center", padding: 24, gap: 12 }}>
      <Text style={{ fontSize: 20, fontWeight: "600" }}>Update required</Text>
      <Text style={{ textAlign: "center" }}>
        {releaseNotes ?? "A new version is required to keep using the app."}
      </Text>
      <TouchableOpacity onPress={() => Linking.openURL("https://your-app-store-link")}>
        <Text style={{ color: "#2563eb" }}>Update now</Text>
      </TouchableOpacity>
    </View>
  );
}

Encourage updates without blocking. Render this above your app content.

UpdateBanner.tsx
import { useForceUpdate } from "@teardown/force-updates";
import { useState } from "react";
import { Linking, Text, TouchableOpacity, View } from "react-native";

export function UpdateBanner() {
  const { isUpdateRecommended, releaseNotes } = useForceUpdate();
  const [dismissed, setDismissed] = useState(false);

  if (!isUpdateRecommended || dismissed) return null;

  return (
    <View style={{ flexDirection: "row", alignItems: "center", gap: 12, padding: 12, backgroundColor: "#eff6ff" }}>
      <Text style={{ flex: 1 }}>{releaseNotes ?? "A new version is available."}</Text>
      <TouchableOpacity onPress={() => Linking.openURL("https://your-app-store-link")}>
        <Text style={{ color: "#2563eb" }}>Update</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => setDismissed(true)}>
        <Text>Dismiss</Text>
      </TouchableOpacity>
    </View>
  );
}

Re-check when the app returns to foreground

By default the version is checked on launch. To also re-check whenever the app comes back to the foreground, pass the AppStateLifecycleAdapter:

teardown.ts
import { TeardownCore, AppStateLifecycleAdapter } from "@teardown/force-updates";

export const teardown = new TeardownCore({
  // ...config, adapters
  lifecycleAdapter: new AppStateLifecycleAdapter(),
});

Tuning checks

Pass a forceUpdate config to control how often checks run.

new TeardownCore({
  // ...
  forceUpdate: {
    checkIntervalMs: 300_000, // minimum time between checks (default: 5 min; -1 disables)
    checkOnForeground: true,  // re-check on foreground (needs lifecycleAdapter)
  },
});

Which versions are allowed, recommended, or blocked is configured per project in the dashboard — no app release needed to change a rule.