forced-expo-update
v0.0.2
Published
Global Expo Updates provider + hook
Downloads
232
Maintainers
Readme
forced-expo-update
A tiny, zero-config Provider for Expo Updates that checks for updates as soon as the app opens and applies them automatically.
The goal is simple:
- Wrap your app once with a Provider
- The library will check/fetch updates on app start
- If there is an update, it will reload the app (configurable)
It also includes optional conveniences:
- Reload immediately or wait for user inactivity ("idle")
- Require a screen-level gate hook to be mounted before an update reload can happen
Install
npm i forced-expo-update@updateThis library requires these peer dependencies in your app:
expo-updatesreactreact-native
Usage (zero config)
Add ExpoUpdatesProvider at the root of your app. That’s it.
import { ExpoUpdatesProvider } from "forced-expo-update";
export function App() {
return <ExpoUpdatesProvider>{/* your app */}</ExpoUpdatesProvider>;
}What happens by default
- The provider waits a small initial delay (a few seconds)
- It checks if an update is available
- If available, it fetches the update
- If a new update was downloaded, it reloads the app
This helps avoid the "update only applies on the next open" feeling.
Enable/Disable globally
You can disable the entire behavior without removing the Provider:
<ExpoUpdatesProvider enabled={false}>{children}</ExpoUpdatesProvider>Options
You can pass optional options to tune behavior.
import { ExpoUpdatesProvider } from "forced-expo-update";
export function App() {
return (
<ExpoUpdatesProvider
options={{
checkIntervalMinutes: 30,
checkOnAppStateChange: true,
reloadImmediately: true,
delayBeforeReloadMs: 3000,
maxRetries: 2,
fetchTimeoutMs: 30000,
}}
>
{children}
</ExpoUpdatesProvider>
);
}Callbacks
<ExpoUpdatesProvider
options={{
onUpdateAvailable: () => {
// update exists on server
},
onUpdateDownloaded: () => {
// update has been downloaded
},
onError: (error) => {
// after max retries
console.log(error);
},
}}
>
{children}
</ExpoUpdatesProvider>Reload strategy: immediate vs idle
Sometimes you don’t want to reload while the user is actively interacting with the app.
This library supports two reload strategies:
"immediate"(default): reloads as soon as an update is downloaded (afterdelayBeforeReloadMs)"whenIdle": waits for a period of inactivity before reloading
Idle reload
<ExpoUpdatesProvider
options={{
reloadStrategy: "whenIdle",
idleReloadAfterMs: 2 * 60 * 1000,
}}
>
{children}
</ExpoUpdatesProvider>Important:
- Even with
"whenIdle", the provider still checks/fetches updates on app start - Only the reload is delayed until the idle timer completes
Screen gate (only reload if a specific screen is mounted)
In some apps you only want to apply updates when the user is on a safe screen (for example, a home screen), not in the middle of a checkout.
Enable gate mode:
<ExpoUpdatesProvider
options={{
gateMode: "requireGate",
}}
>
{children}
</ExpoUpdatesProvider>Then, in the screen(s) where it is safe to reload, mount the gate hook:
import { useExpoUpdatesGate } from "forced-expo-update";
export function HomeScreen() {
useExpoUpdatesGate();
return null;
}How it works:
- If
gateModeis"none"(default), updates can reload anytime - If
gateModeis"requireGate", the Provider will only trigger reload while at least one gate is mounted
Manual check
If you want to manually trigger a check (for example from a settings screen):
import { useExpoUpdates } from "forced-expo-update";
export function Settings() {
const { checkForUpdates } = useExpoUpdates();
const onPress = async () => {
await checkForUpdates();
};
return null;
}Notes
- This library does nothing in development mode (
__DEV__) to avoid disrupting your dev workflow. - Actual update availability depends on your
expo-updatesconfiguration (release channels, runtime version, etc.).
API
ExpoUpdatesProvider
Props:
enabled?: boolean(defaulttrue)options?: ExpoUpdatesOptions
ExpoUpdatesOptions
checkIntervalMinutes?: numbercheckOnAppStateChange?: booleanreloadImmediately?: booleanfetchTimeoutMs?: numbermaxRetries?: numberdelayBeforeReloadMs?: numberreloadStrategy?: "immediate" | "whenIdle"idleReloadAfterMs?: numbergateMode?: "none" | "requireGate"onUpdateAvailable?: () => voidonUpdateDownloaded?: () => voidonError?: (error: Error) => void
Hooks
useExpoUpdates()useExpoUpdatesGate()
License
MIT
