Skip to content

Instantly share code, notes, and snippets.

@wodin
Last active February 27, 2020 11:40
Show Gist options
  • Save wodin/4b337348583fe66886fb743a4500be92 to your computer and use it in GitHub Desktop.
Save wodin/4b337348583fe66886fb743a4500be92 to your computer and use it in GitHub Desktop.
Expo periodic updates
import React, { useEffect, useState } from "react";
import { View } from "react-native";
import {
Button,
FAB,
Provider as PaperProvider,
Text
} from "react-native-paper";
import { Updates } from "expo";
import { SafeAreaProvider, useSafeArea } from "react-native-safe-area-context";
const UpdateButton = props => {
const { visible, top } = props;
return (
<FAB
style={{
position: "absolute",
margin: 16,
right: 0,
top,
backgroundColor: "#36454f"
}}
icon="cloud-download"
label="Update"
color="white"
visible={visible}
onPress={() => Updates.reloadFromCache()}
/>
);
};
const HomeScreen = props => {
const insets = useSafeArea();
const [updateAvailable, setUpdateAvailable] = useState(false);
const [updateState, setUpdateState] = useState(undefined);
const [tick, setTick] = useState(0);
useEffect(() => {
if (!__DEV__) {
Updates.checkForUpdateAsync().then(({ isAvailable, manifest }) => {
if (isAvailable) {
Updates.fetchUpdateAsync({
eventListener: ({ type, manifest, message }) => {
if (type === Updates.EventType.DOWNLOAD_STARTED) {
setUpdateState("Downloading update");
} else if (type === Updates.EventType.DOWNLOAD_FINISHED) {
setUpdateAvailable(true);
setUpdateState(undefined);
} else if (type === Updates.EventType.NO_UPDATE_AVAILABLE) {
setUpdateAvailable(false);
setUpdateState("Already running latest version");
} else if (type === Updates.EventType.ERROR) {
setUpdateAvailable(false);
setUpdateState(`ERROR: ${message}`);
} else {
setUpdateAvailable(false);
setUpdateState(`Unexpected Updates state: ${type}`);
}
}
})
.then(({ isNew, manifest }) => {
if (isNew) {
console.log("Got new bundle!", JSON.stringify(manifest));
} else {
alert("Got old bundle? " + JSON.stringify(manifest));
}
})
.catch(error => {
alert("Error fetching new bundle " + JSON.stringify(error));
});
}
});
}
}, [tick]);
return (
<View
style={{
flex: 1,
justifyContent: "space-around",
alignItems: "center",
paddingTop: insets.top
}}
>
<Text style={{ paddingHorizontal: 20 }}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</Text>
<Button
mode="contained"
color="#3f56b5"
uppercase={false}
style={{ margin: 10 }}
contentStyle={{ flex: 0, justifyContent: "flex-start", width: 175 }}
labelStyle={{ fontSize: 20 }}
onPress={() => {
/* Do something */
alert("Doing something");
// Also trigger a check for updates if at least 6 hours has passed
if (Date.now() - tick > 1000 * 60 * 60 * 6) setTick(Date.now());
}}
>
Do something
</Button>
<UpdateButton visible={updateAvailable} top={insets.top} />
{updateState && (
<View
style={{
position: "absolute",
margin: 16,
bottom: insets.bottom
}}
>
<Text>{updateState}</Text>
</View>
)}
</View>
);
};
export default function App() {
return (
<PaperProvider>
<SafeAreaProvider>
<HomeScreen />
</SafeAreaProvider>
</PaperProvider>
);
}
{
"expo": {
[...]
"updates": {
"checkAutomatically": "ON_ERROR_RECOVERY",
"fallbackToCacheTimeout": 0
},
[...]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment