jutsu-expo:expo-updates

Use this skill when implementing over-the-air (OTA) updates to deploy JavaScript and asset updates without app store releases.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "jutsu-expo:expo-updates" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-jutsu-expo-expo-updates

Expo Updates

Use this skill when implementing over-the-air (OTA) updates to deploy JavaScript and asset updates without app store releases.

Key Concepts

Configuration

// app.json { "expo": { "updates": { "enabled": true, "checkAutomatically": "ON_LOAD", "fallbackToCacheTimeout": 0, "url": "https://u.expo.dev/[project-id]" }, "runtimeVersion": { "policy": "sdkVersion" } } }

Checking for Updates

import * as Updates from 'expo-updates'; import { useEffect, useState } from 'react'; import { View, Text, Button } from 'react-native';

export default function App() { const [updateAvailable, setUpdateAvailable] = useState(false);

useEffect(() => { async function checkForUpdates() { if (!DEV) { const update = await Updates.checkForUpdateAsync(); setUpdateAvailable(update.isAvailable); } } checkForUpdates(); }, []);

const handleUpdate = async () => { const { isNew } = await Updates.fetchUpdateAsync(); if (isNew) { await Updates.reloadAsync(); } };

if (updateAvailable) { return ( <View> <Text>Update Available!</Text> <Button title="Update Now" onPress={handleUpdate} /> </View> ); }

return <View>{/* Your app */}</View>; }

Runtime Versions

// app.config.ts export default { expo: { runtimeVersion: { policy: 'appVersion', // Match app version }, // Or use custom logic runtimeVersion: '1.0.0', }, };

Best Practices

Update Hook

import * as Updates from 'expo-updates'; import { useEffect, useState } from 'react';

export function useUpdates() { const [isChecking, setIsChecking] = useState(false); const [isDownloading, setIsDownloading] = useState(false); const [updateAvailable, setUpdateAvailable] = useState(false);

useEffect(() => { const subscription = Updates.addListener((event) => { if (event.type === Updates.UpdateEventType.UPDATE_AVAILABLE) { setUpdateAvailable(true); } });

return () => subscription.remove();

}, []);

const checkForUpdate = async () => { if (DEV) return;

setIsChecking(true);
try {
  const update = await Updates.checkForUpdateAsync();
  setUpdateAvailable(update.isAvailable);
} finally {
  setIsChecking(false);
}

};

const downloadAndApplyUpdate = async () => { if (DEV) return;

setIsDownloading(true);
try {
  const update = await Updates.fetchUpdateAsync();
  if (update.isNew) {
    await Updates.reloadAsync();
  }
} finally {
  setIsDownloading(false);
}

};

return { isChecking, isDownloading, updateAvailable, checkForUpdate, downloadAndApplyUpdate, }; }

Silent Updates

import { useEffect } from 'react'; import * as Updates from 'expo-updates';

export function useSilentUpdates() { useEffect(() => { async function update() { if (DEV) return;

  try {
    const update = await Updates.checkForUpdateAsync();
    if (update.isAvailable) {
      await Updates.fetchUpdateAsync();
      // Don't reload immediately - wait for next app start
    }
  } catch (error) {
    console.error('Update check failed:', error);
  }
}

update();

}, []); }

Common Patterns

Update Screen

import * as Updates from 'expo-updates'; import { useState } from 'react'; import { View, Text, Button, ActivityIndicator } from 'react-native';

export function UpdateScreen() { const [loading, setLoading] = useState(false);

const handleUpdate = async () => { setLoading(true); try { const update = await Updates.fetchUpdateAsync(); if (update.isNew) { await Updates.reloadAsync(); } } catch (error) { console.error('Update failed:', error); } finally { setLoading(false); } };

if (loading) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <ActivityIndicator size="large" /> <Text>Updating...</Text> </View> ); }

return ( <View> <Text>Update Available</Text> <Button title="Update Now" onPress={handleUpdate} /> </View> ); }

EAS Update Configuration

// eas.json { "build": { "production": { "channel": "production" }, "preview": { "channel": "preview" } } }

Related Skills

  • expo-config: Configuring updates

  • expo-build: Building with EAS

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review
General

atomic-design-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review