Skip to main content
The library provides synchronous access to all app version information. These values are cached at module initialization, so repeated reads have zero native overhead—no bridge calls, no async operations.

Synchronous properties

All version information is available immediately through the VersionCheck object:
import { VersionCheck } from 'react-native-nitro-version-check';

VersionCheck.version;       // "1.2.0"
VersionCheck.buildNumber;   // "42"
VersionCheck.packageName;   // "com.example.app"
VersionCheck.installSource; // "appstore" | "testflight" | "playstore" | undefined
VersionCheck.getCountry();  // "US"
These properties are cached at module init time, ensuring zero JSI overhead on repeated access. The values are plain JavaScript strings, not native calls.

Version string

The current app version as a string.
VersionCheck.version // "1.2.0"

Platform mapping

Reads from CFBundleShortVersionString in your Info.plist:
<key>CFBundleShortVersionString</key>
<string>1.2.0</string>
This is the user-facing version number displayed in the App Store.

Build number

The current build number or version code as a string.
VersionCheck.buildNumber // "42"

Platform mapping

Reads from CFBundleVersion in your Info.plist:
<key>CFBundleVersion</key>
<string>42</string>
This is the build number that increments with each App Store submission.
Use buildNumber for internal tracking and debugging. It’s particularly useful for crash reporting and support tickets.

Package name

The app’s unique identifier (Bundle ID on iOS, Application ID on Android).
VersionCheck.packageName // "com.example.app"

Platform mapping

Reads the Bundle ID from your Info.plist:
<key>CFBundleIdentifier</key>
<string>com.example.app</string>

Install source

Detects where the app was installed from. Returns undefined for development builds or sideloaded apps.
VersionCheck.installSource // "appstore" | "testflight" | "playstore" | undefined

Possible values

type InstallSource = "appstore" | "testflight" | undefined

if (VersionCheck.installSource === "testflight") {
  // Running a TestFlight build
  enableBetaFeatures();
}

if (VersionCheck.installSource === "appstore") {
  // Production App Store build
}

if (VersionCheck.installSource === undefined) {
  // Development build or sideloaded
}

Use cases

const showBetaUI = VersionCheck.installSource === "testflight";

return (
  <View>
    {showBetaUI && <BetaFeaturePanel />}
    <MainContent />
  </View>
);
if (VersionCheck.installSource === "appstore" || VersionCheck.installSource === "playstore") {
  // Only track analytics for production builds
  Analytics.init(API_KEY);
}
const isDevelopment = VersionCheck.installSource === undefined;

if (isDevelopment) {
  console.log("Running in development mode");
  enableDebugMenu();
}

Device country

Returns the device’s current 2-letter ISO country code.
VersionCheck.getCountry() // "US"
This is a synchronous Nitro call—no await needed. The country code is determined by the device’s locale settings, not GPS or IP address.

Use cases

const country = VersionCheck.getCountry();

const supportEmail = country === "US" 
  ? "[email protected]" 
  : "[email protected]";
const country = VersionCheck.getCountry();
const showPaymentFeature = ["US", "CA", "GB"].includes(country);
const country = VersionCheck.getCountry();
const theme = country === "CN" ? chineseTheme : defaultTheme;

How caching works

All properties except getCountry() are cached as plain JavaScript values at module initialization:
// From source: package/src/index.ts
const HybridVersionCheck = NitroModules.createHybridObject<VersionCheckType>("VersionCheck");

// Cached at module init — plain JS values, no JSI overhead on repeated access.
const version = HybridVersionCheck.version;
const buildNumber = HybridVersionCheck.buildNumber;
const packageName = HybridVersionCheck.packageName;
const installSource = HybridVersionCheck.installSource;
This means:
1

Module loads

When the module is first imported, it reads all properties from native once.
2

Values cached

These values are stored as plain JavaScript strings in memory.
3

Zero overhead access

Every subsequent access reads from the cached JavaScript value—no bridge call, no JSI call, just a variable lookup.
You can access these properties thousands of times per second without any performance impact. They’re just plain JavaScript variables.

Complete example

Here’s a settings screen that displays all version information:
import { VersionCheck } from 'react-native-nitro-version-check';
import { View, Text, StyleSheet } from 'react-native';

export default function SettingsScreen() {
  return (
    <View style={styles.container}>
      <Text style={styles.label}>Version: {VersionCheck.version}</Text>
      <Text style={styles.label}>Build: {VersionCheck.buildNumber}</Text>
      <Text style={styles.label}>Package: {VersionCheck.packageName}</Text>
      <Text style={styles.label}>Country: {VersionCheck.getCountry()}</Text>
      <Text style={styles.label}>
        Install: {VersionCheck.installSource ?? "Dev Build"}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 24,
  },
  label: {
    fontSize: 15,
    marginVertical: 2,
  },
});

Comparison with other libraries

Traditional React Native libraries require async bridge calls to read native values. With Nitro Modules, all version info is synchronous and cached.
// ❌ Old approach (react-native-device-info)
import DeviceInfo from 'react-native-device-info';
const version = await DeviceInfo.getVersion(); // Async bridge call

// ✅ Nitro approach (this library)
import { VersionCheck } from 'react-native-nitro-version-check';
const version = VersionCheck.version; // Instant, cached value

Best practices

  1. Import once, use everywhere: The cached values are shared across your entire app
  2. No useEffect needed: These are synchronous values, safe to use directly in render
  3. Perfect for crash reports: Include version, buildNumber, and installSource in all error logs
  4. Combine with update checks: Use version alongside needsUpdate() to show before/after versions
import { VersionCheck, needsUpdate, getLatestVersion } from 'react-native-nitro-version-check';

if (await needsUpdate()) {
  const latest = await getLatestVersion();
  console.log(`Update available: ${VersionCheck.version}${latest}`);
}

Build docs developers (and LLMs) love