┌───────────────────────────────┐ │ EAS Update Demo │ ├───────────────────────────────┤ │ Status: Checking for updates...│ │ │ │ [Check for Update] │ │ │ │ [Apply Update] │ │ │ │ Last update: None │ └───────────────────────────────┘
Over-the-air updates (EAS Update) in React Native - Mini App: Build & Ship
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' } });
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.
┌───────────────────────────────┐ │ EAS Update Demo │ ├───────────────────────────────┤ │ Status: Up to date │ │ │ │ [Check for Update] │ │ │ │ [Apply Update] (disabled) │ │ │ │ Last update: None │ └───────────────────────────────┘
Practice
What is the main benefit of using Over-the-air (OTA) updates with EAS Update in a React Native app?
Solution
Step 1: Understand OTA update purpose
OTA updates let developers fix bugs and add features quickly without app store delays.Step 2: Compare options
Only Fix bugs and add features without waiting for app store approval describes this benefit correctly; others describe drawbacks or unrelated effects.Final Answer:
Fix bugs and add features without waiting for app store approval -> Option AQuick Check:
OTA updates = fast fixes and features [OK]
- Thinking OTA updates increase app size
- Believing users must reinstall app for OTA
- Assuming app disables during update
Which of the following is the correct way to import the Expo Updates API in a React Native app?
?Solution
Step 1: Recall Expo Updates import syntax
The official Expo Updates API is imported using "import * as Updates from 'expo-updates';".Step 2: Check other options
Options A, B, and C use incorrect package names or import styles not recommended for Expo Updates.Final Answer:
import * as Updates from 'expo-updates'; -> Option DQuick Check:
Correct import = import * as Updates from 'expo-updates'; [OK]
- Using wrong package name like 'react-native-updates'
- Using require instead of import
- Importing Updates from 'expo' instead of 'expo-updates'
Given this React Native code snippet using Expo Updates API, what will be logged if an update is available?
import * as Updates from 'expo-updates';
async function checkUpdate() {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
console.log('Update found!');
} else {
console.log('No update available.');
}
}
checkUpdate();Solution
Step 1: Analyze checkForUpdateAsync result
The function returns an object with isAvailable true if an update exists.Step 2: Follow the if condition
If update.isAvailable is true, it logs 'Update found!'. Otherwise, logs 'No update available.'Final Answer:
Update found! -> Option CQuick Check:
Update available logs 'Update found!' [OK]
- Confusing checkForUpdateAsync return value
- Expecting syntax error from async function
- Thinking nothing logs without await
Identify the error in this code snippet that tries to fetch and reload an update using Expo Updates API:
import * as Updates from 'expo-updates';
async function updateApp() {
const update = Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
Updates.reloadAsync();
}
}Solution
Step 1: Check async function usage
Updates.checkForUpdateAsync() returns a Promise and must be awaited to get the result.Step 2: Identify missing await impact
Without await, update is a Promise, so update.isAvailable is undefined causing error.Final Answer:
Missing await before Updates.checkForUpdateAsync() -> Option BQuick Check:
Always await async calls to get results [OK]
- Forgetting await on async functions
- Calling reloadAsync() before fetching update
- Assuming fetchUpdateAsync() is synchronous
You want your React Native app to check for OTA updates on app start, download them silently, and apply on next app reload. Which approach correctly implements this behavior?
?Solution
Step 1: Understand OTA update flow
Check for update availability first, then fetch update silently if available.Step 2: Apply update on next reload
Fetching update downloads it; reloadAsync applies update immediately, but we want to apply on next app start.Final Answer:
Use Updates.checkForUpdateAsync(), then if available, call Updates.fetchUpdateAsync() without reload, apply on next start -> Option AQuick Check:
Check, fetch silently, reload later = Use Updates.checkForUpdateAsync(), then if available, call Updates.fetchUpdateAsync() without reload, apply on next start [OK]
- Reloading app immediately causing bad UX
- Fetching update without checking availability
- Reloading without fetching update
Ready to prove it?
Pass the test and this pattern moves unknown
