0
0
React Nativemobile~20 mins

Over-the-air updates (EAS Update) in React Native - Mini App: Build & Ship

Choose your learning style9 modes available
Build: EAS Update Demo
This screen shows how to check for and apply over-the-air updates using Expo Application Services (EAS) Update in a React Native app.
Target UI
┌───────────────────────────────┐
│        EAS Update Demo         │
├───────────────────────────────┤
│ Status: Checking for updates...│
│                               │
│ [Check for Update]             │
│                               │
│ [Apply Update]                │
│                               │
│ Last update: None             │
└───────────────────────────────┘
Display current update status text (e.g., 'Checking for updates...', 'Up to date', 'Update available').
Add a button labeled 'Check for Update' that checks if an update is available.
Add a button labeled 'Apply Update' that downloads and reloads the app if an update is found.
Show the last update time or 'None' if no update applied yet.
Handle errors gracefully and show error messages in the status text.
Starter Code
React Native
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import * as Updates from 'expo-updates';

export default function EASUpdateDemo() {
  const [status, setStatus] = useState('Idle');
  const [lastUpdate, setLastUpdate] = useState('None');

  // TODO: Implement checkForUpdate function

  // TODO: Implement applyUpdate function

  return (
    <View style={styles.container}>
      <Text style={styles.title}>EAS Update Demo</Text>
      <Text style={styles.status}>Status: {status}</Text>
      <View style={styles.buttonContainer}>
        <Button title="Check for Update" onPress={() => {}} />
      </View>
      <View style={styles.buttonContainer}>
        <Button title="Apply Update" onPress={() => {}} disabled />
      </View>
      <Text style={styles.lastUpdate}>Last update: {lastUpdate}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 },
  title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20 },
  status: { fontSize: 16, marginBottom: 20 },
  buttonContainer: { marginVertical: 10, width: '60%' },
  lastUpdate: { marginTop: 30, fontSize: 14, fontStyle: 'italic' }
});
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
React Native
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import * as Updates from 'expo-updates';

export default function EASUpdateDemo() {
  const [status, setStatus] = useState('Idle');
  const [lastUpdate, setLastUpdate] = useState('None');
  const [updateAvailable, setUpdateAvailable] = useState(false);

  async function checkForUpdate() {
    setStatus('Checking for updates...');
    try {
      const update = await Updates.checkForUpdateAsync();
      if (update.isAvailable) {
        setStatus('Update available');
        setUpdateAvailable(true);
      } else {
        setStatus('Up to date');
        setUpdateAvailable(false);
      }
    } catch (e) {
      setStatus('Error checking updates');
      setUpdateAvailable(false);
    }
  }

  async function applyUpdate() {
    setStatus('Downloading update...');
    try {
      await Updates.fetchUpdateAsync();
      setStatus('Applying update...');
      await Updates.reloadAsync();
      // After reload, this code runs fresh, so lastUpdate resets
    } catch (e) {
      setStatus('Error applying update');
    }
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>EAS Update Demo</Text>
      <Text style={styles.status}>Status: {status}</Text>
      <View style={styles.buttonContainer}>
        <Button title="Check for Update" onPress={checkForUpdate} />
      </View>
      <View style={styles.buttonContainer}>
        <Button title="Apply Update" onPress={applyUpdate} disabled={!updateAvailable} />
      </View>
      <Text style={styles.lastUpdate}>Last update: {lastUpdate}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 },
  title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20 },
  status: { fontSize: 16, marginBottom: 20 },
  buttonContainer: { marginVertical: 10, width: '60%' },
  lastUpdate: { marginTop: 30, fontSize: 14, fontStyle: 'italic' }
});

This React Native screen uses Expo Updates API to check and apply over-the-air updates.

When the user taps 'Check for Update', the app calls Updates.checkForUpdateAsync() to see if a new update is available. The status text updates to show the result.

If an update is available, the 'Apply Update' button becomes enabled. When tapped, it downloads the update with Updates.fetchUpdateAsync() and then reloads the app with Updates.reloadAsync() to apply the update immediately.

Errors during checking or applying updates are caught and shown in the status text.

The last update time is shown but remains 'None' here because this example does not persist update timestamps across reloads. In a real app, you could save the update time in persistent storage.

Final Result
Completed Screen
┌───────────────────────────────┐
│        EAS Update Demo         │
├───────────────────────────────┤
│ Status: Up to date             │
│                               │
│ [Check for Update]             │
│                               │
│ [Apply Update] (disabled)      │
│                               │
│ Last update: None             │
└───────────────────────────────┘
Tapping 'Check for Update' changes status to 'Checking for updates...' then 'Up to date' or 'Update available'.
If update is available, 'Apply Update' button becomes enabled.
Tapping 'Apply Update' downloads and reloads the app to apply the update.
If errors occur, status shows error messages.
Stretch Goal
Add a timestamp showing when the last successful update was applied, saved persistently.
💡 Hint
Use React Native AsyncStorage or Expo SecureStore to save the update time before calling reloadAsync, then read it on app start.