This library is a drop-in replacement for the unmaintained react-native-version-check , rewritten from scratch using Nitro Modules for better performance and modern React Native support.
Why migrate?
react-native-version-check is unmaintained
The original library has not been updated since 2021 and doesn’t support modern React Native versions.
Built with Nitro Modules
This library uses Nitro Modules for direct C++ to JavaScript communication, eliminating the old React Native bridge entirely.
Better performance
Synchronous access to version properties (no await needed)
Zero overhead on repeated property access (cached at init)
Up to 40x faster for property reads compared to bridge-based libraries
Modern React Native support
Built for React Native 0.75+ with full new architecture support out of the box.
Installation
First, remove the old library:
npm uninstall react-native-version-check
# or
yarn remove react-native-version-check
Then install the new one:
npm install react-native-nitro-version-check
# or
yarn add react-native-nitro-version-check
API differences
The new library has a cleaner, more modern API surface. Here’s a complete mapping:
Old (react-native-version-check)
New (react-native-nitro-version-check)
import VersionCheck from 'react-native-version-check' ;
// All properties were async
const version = await VersionCheck . getCurrentVersion ();
const buildNumber = await VersionCheck . getCurrentBuildNumber ();
const packageName = await VersionCheck . getPackageName ();
const country = await VersionCheck . getCountry ();
Breaking change : All version properties are now synchronous . Remove await and update your code accordingly.
Update checking
Old (react-native-version-check)
New (react-native-nitro-version-check)
import VersionCheck from 'react-native-version-check' ;
// Check for any update
const needsUpdate = await VersionCheck . needsUpdate ();
// Check with options
const needsUpdate = await VersionCheck . needsUpdate ({
depth: 2 , // Check minor versions
});
// Get latest version
const latest = await VersionCheck . getLatestVersion ();
The new API uses semantic versioning terminology ("major", "minor", "patch") instead of numeric depth values.
Opening the store
Old (react-native-version-check)
New (react-native-nitro-version-check)
import VersionCheck from 'react-native-version-check' ;
const url = await VersionCheck . getStoreUrl ();
VersionCheck . openAppStore (); // Had built-in method
The new library doesn’t include a built-in openAppStore() method. Use React Native’s Linking.openURL() for better flexibility and control.
Migration checklist
Use this checklist to ensure a smooth migration:
Update imports
Change all imports from react-native-version-check to react-native-nitro-version-check: // Before
import VersionCheck from 'react-native-version-check' ;
// After
import { VersionCheck , needsUpdate , getStoreUrl } from 'react-native-nitro-version-check' ;
Remove await from version properties
Update all version property accesses to be synchronous: // Before
const version = await VersionCheck . getCurrentVersion ();
const buildNumber = await VersionCheck . getCurrentBuildNumber ();
// After
const version = VersionCheck . version ;
const buildNumber = VersionCheck . buildNumber ;
Update needsUpdate() calls
Replace depth with level using semantic versioning terms: // Before
await VersionCheck . needsUpdate ({ depth: 1 }); // Major
await VersionCheck . needsUpdate ({ depth: 2 }); // Minor
await VersionCheck . needsUpdate ({ depth: 3 }); // Patch
// After
await needsUpdate ({ level: "major" });
await needsUpdate ({ level: "minor" });
await needsUpdate ({ level: "patch" });
Replace openAppStore()
Replace built-in store opening with React Native’s Linking: // Before
VersionCheck . openAppStore ();
// After
import { Linking } from 'react-native' ;
const url = await getStoreUrl ();
Linking . openURL ( url );
Test thoroughly
Verify version info displays correctly
Test update checks on both iOS and Android
Confirm store URLs open correctly
Check behavior in TestFlight/beta builds
Complete migration example
Here’s a side-by-side comparison of a complete update checking flow:
Before (old library)
After (new library)
import { useEffect , useState } from 'react' ;
import { View , Text , TouchableOpacity } from 'react-native' ;
import VersionCheck from 'react-native-version-check' ;
export default function UpdateChecker () {
const [ version , setVersion ] = useState < string | null >( null );
const [ needsUpdate , setNeedsUpdate ] = useState ( false );
useEffect (() => {
const checkUpdate = async () => {
// All async calls
const currentVersion = await VersionCheck . getCurrentVersion ();
setVersion ( currentVersion );
const updateNeeded = await VersionCheck . needsUpdate ({
depth: 2 , // Check minor versions
});
setNeedsUpdate ( updateNeeded );
};
checkUpdate ();
}, []);
const handleUpdate = () => {
VersionCheck . openAppStore ();
};
return (
< View >
< Text > Version : { version }</ Text >
{ needsUpdate && (
< TouchableOpacity onPress = { handleUpdate } >
< Text > Update Available </ Text >
</ TouchableOpacity >
)}
</ View >
);
}
import { useEffect , useState } from 'react' ;
import { View , Text , TouchableOpacity , Linking } from 'react-native' ;
import { VersionCheck , needsUpdate , getStoreUrl } from 'react-native-nitro-version-check' ;
export default function UpdateChecker () {
// No useState for version - it's synchronous now!
const [ updateNeeded , setUpdateNeeded ] = useState ( false );
const [ storeUrl , setStoreUrl ] = useState < string | null >( null );
useEffect (() => {
const checkUpdate = async () => {
// Only async calls go in useEffect
const isUpdateNeeded = await needsUpdate ({ level: "minor" });
setUpdateNeeded ( isUpdateNeeded );
if ( isUpdateNeeded ) {
const url = await getStoreUrl ();
setStoreUrl ( url );
}
};
checkUpdate ();
}, []);
const handleUpdate = () => {
if ( storeUrl ) {
Linking . openURL ( storeUrl );
}
};
return (
< View >
{ /* Synchronous access - no loading state needed */ }
< Text > Version : { VersionCheck . version }</ Text >
< Text > Build : { VersionCheck . buildNumber }</ Text >
{ updateNeeded && (
< TouchableOpacity onPress = { handleUpdate } >
< Text > Update Available </ Text >
</ TouchableOpacity >
)}
</ View >
);
}
New features
The new library includes features not available in the old one:
Install source detection
Detect where your app was installed from:
import { VersionCheck } from 'react-native-nitro-version-check' ;
if ( VersionCheck . installSource === "testflight" ) {
// Running a TestFlight build - enable beta features
}
if ( VersionCheck . installSource === "appstore" || VersionCheck . installSource === "playstore" ) {
// Production build
}
Values:
iOS: "appstore", "testflight", or undefined
Android: "playstore" or undefined
Cached properties
All version properties are cached at module initialization for zero overhead:
// These are plain JavaScript values - no native calls
for ( let i = 0 ; i < 1000000 ; i ++ ) {
const v = VersionCheck . version ; // Instant, no bridge overhead
}
Semantic versioning utilities
Use the built-in semantic version comparison:
import { compareVersions } from 'react-native-nitro-version-check' ;
compareVersions ( "1.2.0" , "1.3.0" ); // -1 (first is older)
compareVersions ( "2.0.0" , "1.9.9" ); // 1 (first is newer)
compareVersions ( "1.0.0" , "1.0.0" ); // 0 (equal)
Troubleshooting
TypeScript errors after migration
Make sure you’ve updated all method names and removed await from synchronous properties: // ❌ Wrong
const version = await VersionCheck . getCurrentVersion ();
// ✅ Correct
const version = VersionCheck . version ;
Nitro Modules requires additional setup. Check the installation guide to ensure:
You’ve run pod install on iOS
Gradle is configured correctly on Android
You’re using React Native 0.75 or higher
needsUpdate() always returns false
The new library uses strict semantic versioning. Make sure:
Your app is published in the store
The package name/bundle ID matches exactly
You’re using the correct level parameter
// Check what level you actually need
const major = await needsUpdate ({ level: "major" });
const minor = await needsUpdate ({ level: "minor" });
const patch = await needsUpdate ({ level: "patch" });
console . log ({ major , minor , patch });
Getting help
If you encounter issues during migration:
Check the API Reference for detailed documentation
Review the installation guide for setup issues
Open an issue on GitHub
The new library is simpler and more performant. Most migrations take less than 30 minutes.