Use animated Lottie splash screen on React Native Expo
How to use Lottie animations as a custom splash screen in Expo
The SplashScreen module from the expo-splash-screen library is used to tell the splash screen to remain visible until it has been explicitly told to hide. This is useful to do tasks that will happen behind the scenes such as making API calls, pre-loading fonts, animating the splash screen and so on.
import * as SplashScreen from 'expo-splash-screen';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { View, Animated, Easing, StyleSheet } from 'react-native';
import { Application } from './src/containers/Application';
import { useResources } from './src/hooks';
import LottieView from 'lottie-react-native';
SplashScreen.preventAutoHideAsync();
const LOTTIE_JSON = require('./assets/splash_animation.json');
export default function App() {
const animationProgress = useRef(new Animated.Value(0));
const [isLayoutReady, setLayoutReady] = useState<boolean>(false);
const [isAppReady, setAppReady] = useState<boolean>(false);
const { isReady } = useResources();
useEffect(() => {
Animated.loop(
Animated.timing(animationProgress.current, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true,
}),
).start();
}, []);
const onApplicationReady = useCallback(() => {
setAppReady(true);
}, []);
const onLayout = useCallback(async () => {
try {
await SplashScreen.hideAsync();
} catch (e) {
// handle errors
} finally {
setLayoutReady(true);
}
}, []);
const showAnimation = !(isAppReady && isLayoutReady && isReady);
return (
<SafeAreaProvider>
{isReady && (
<Application onReady={onApplicationReady} />
)}
{showAnimation && (
<View
pointerEvents="none"
style={[StyleSheet.absoluteFill, styles.splashContainer]}
onLayout={onLayout}
>
<LottieView
style={{
width: 200,
height: 200,
backgroundColor: 'green',
}}
source={LOTTIE_JSON}
progress={animationProgress.current}
/>
</View>
)}
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
splashContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'green',
},
}); The useResources() custom hook has an async load method to fetch data from the server and load other assets like fonts and images.
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { MainStackNavigator } from '../components/navigation';
export function Application(props: { onReady: () => void }) {
const onNavigationReady = () => {
props.onReady();
};
return (
<NavigationContainer onReady={onNavigationReady}>
<MainStackNavigator />
</NavigationContainer>
);
} When the NavigationContainer is ready, it calls the onReady callback function, which triggers the main App component to hide the Lottie animation view.
Conclusion
This approach combines Expo’s SplashScreen API with Lottie animations to create a polished app launch experience. The animation plays while the app loads, then transitions seamlessly to the main content.