expo-splash-screen
Version: 55.0.6
Provides a module to keep the native Splash Screen visible until you choose to hide it. Useful for loading fonts, assets, or data before showing your app.
Installation
npx expo install expo-splash-screen
Usage
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
// Keep the splash screen visible while we fetch resources
SplashScreen.preventAutoHideAsync();
function App() {
useEffect(() => {
async function prepare() {
try {
// Pre-load fonts, make API calls, etc.
await loadResourcesAsync();
} catch (e) {
console.warn(e);
} finally {
// Tell the application to render
await SplashScreen.hideAsync();
}
}
prepare();
}, []);
return <YourApp />;
}
API Reference
Methods
SplashScreen.preventAutoHideAsync()
Prevents the splash screen from auto-hidingawait SplashScreen.preventAutoHideAsync();
Call this before rendering your root component to prevent the splash screen from disappearing automatically.
Hides the splash screenawait SplashScreen.hideAsync();
Call this after your app has finished loading resources and is ready to display.
SplashScreen.setOptions(options)
(options: SplashScreenOptions) => Promise<void>
Android only: Configure splash screen behaviorawait SplashScreen.setOptions({
duration: 1000,
fade: true
});
Examples
Basic Usage with Asset Loading
import * as SplashScreen from 'expo-splash-screen';
import { Asset } from 'expo-asset';
import { useEffect, useState } from 'react';
SplashScreen.preventAutoHideAsync();
function App() {
const [appIsReady, setAppIsReady] = useState(false);
useEffect(() => {
async function prepare() {
try {
// Load fonts
await Font.loadAsync({
'Inter-Bold': require('./assets/fonts/Inter-Bold.ttf'),
});
// Load assets
await Asset.loadAsync([
require('./assets/images/logo.png'),
]);
// Artificial delay for demo
await new Promise(resolve => setTimeout(resolve, 2000));
} catch (e) {
console.warn(e);
} finally {
setAppIsReady(true);
}
}
prepare();
}, []);
useEffect(() => {
if (appIsReady) {
SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return <YourApp />;
}
With React Navigation
import * as SplashScreen from 'expo-splash-screen';
import { NavigationContainer } from '@react-navigation/native';
import { useCallback, useEffect, useState } from 'react';
import { View } from 'react-native';
SplashScreen.preventAutoHideAsync();
function App() {
const [appIsReady, setAppIsReady] = useState(false);
useEffect(() => {
async function prepare() {
try {
// Pre-load resources here
await loadResources();
} catch (e) {
console.warn(e);
} finally {
setAppIsReady(true);
}
}
prepare();
}, []);
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return (
<View style={{ flex: 1 }} onLayout={onLayoutRootView}>
<NavigationContainer>
{/* Your navigation */}
</NavigationContainer>
</View>
);
}
Animated Splash Screen Transition
import * as SplashScreen from 'expo-splash-screen';
import { useEffect, useState } from 'react';
import { Animated, StyleSheet } from 'react-native';
SplashScreen.preventAutoHideAsync();
function App() {
const [appIsReady, setAppIsReady] = useState(false);
const [fadeAnim] = useState(new Animated.Value(0));
useEffect(() => {
async function prepare() {
try {
await loadResources();
} catch (e) {
console.warn(e);
} finally {
setAppIsReady(true);
}
}
prepare();
}, []);
useEffect(() => {
if (appIsReady) {
// Hide splash and fade in app
SplashScreen.hideAsync().then(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}).start();
});
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return (
<Animated.View style={[styles.container, { opacity: fadeAnim }]}>
<YourApp />
</Animated.View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 }
});
Error Handling
import * as SplashScreen from 'expo-splash-screen';
import { useEffect, useState } from 'react';
import { Text, View } from 'react-native';
SplashScreen.preventAutoHideAsync();
function App() {
const [appIsReady, setAppIsReady] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
async function prepare() {
try {
await loadCriticalResources();
setAppIsReady(true);
} catch (e) {
setError(e as Error);
} finally {
await SplashScreen.hideAsync();
}
}
prepare();
}, []);
if (error) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Error loading app: {error.message}</Text>
</View>
);
}
if (!appIsReady) {
return null;
}
return <YourApp />;
}
With Multiple Loading Steps
import * as SplashScreen from 'expo-splash-screen';
import { useEffect, useState } from 'react';
SplashScreen.preventAutoHideAsync();
function App() {
const [progress, setProgress] = useState(0);
useEffect(() => {
async function prepare() {
try {
// Step 1: Load fonts (33%)
await loadFonts();
setProgress(33);
// Step 2: Load assets (66%)
await loadAssets();
setProgress(66);
// Step 3: Initialize app (100%)
await initializeApp();
setProgress(100);
} catch (e) {
console.warn(e);
} finally {
await SplashScreen.hideAsync();
}
}
prepare();
}, []);
if (progress < 100) {
return null;
}
return <YourApp />;
}
Configuration
app.json:
{
"expo": {
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
}
}
Advanced Configuration
{
"expo": {
"splash": {
"image": "./assets/splash.png",
"resizeMode": "cover",
"backgroundColor": "#1E1E1E",
"imageLight": "./assets/splash-light.png",
"imageDark": "./assets/splash-dark.png"
},
"android": {
"splash": {
"image": "./assets/splash-android.png",
"resizeMode": "native",
"backgroundColor": "#000000"
}
},
"ios": {
"splash": {
"image": "./assets/splash-ios.png",
"resizeMode": "cover",
"backgroundColor": "#FFFFFF",
"tabletImage": "./assets/splash-tablet.png"
}
}
}
}
TypeScript
import * as SplashScreen from 'expo-splash-screen';
// Prevent auto-hide
const prevented: boolean = await SplashScreen.preventAutoHideAsync();
// Hide splash
const hidden: boolean = await SplashScreen.hideAsync();
| Platform | Supported |
|---|
| iOS | ✅ |
| Android | ✅ |
| Web | ❌ |
On web, there is no native splash screen. Use a custom loading component instead.
Best Practices
- Call preventAutoHideAsync Early: Call it at the module level, before any component renders
- Always Hide: Always call
hideAsync() in a finally block to ensure the splash screen is hidden
- Handle Errors: Catch and handle errors during loading to prevent stuck splash screen
- Optimize Loading: Only load critical resources during splash screen
- Test on Device: Splash screen behavior can differ between simulator and device
If you never call SplashScreen.hideAsync(), your app will remain stuck on the splash screen.
Resources