Skip to content

SplashScreen

andreiradchenko edited this page Apr 30, 2024 · 2 revisions

Splash Screen

Expo Splash Screen | app.json parameters | White screen issue | Create splash and icon

Splash screen is the initial screen users see when the app is launched, before it has loaded. Imported and started (prevented from closing) in app.js

app.js

import * as SplashScreen from 'expo-splash-screen';

SplashScreen.preventAutoHideAsync();

export default function App() {
  const [fontsLoaded] = useFonts({
    'Roboto-Regular': require('./assets/fonts/roboto/Roboto-Regular.ttf'),
    'Roboto-Bold': require('./assets/fonts/roboto/Roboto-Bold.ttf'),
  });

  const onLayoutRootView = useCallback(async () => {
    if (fontsLoaded) {
      await SplashScreen.hideAsync();
    }
  }, [fontsLoaded]);

  if (!fontsLoaded) {
    return null;
  }

  return (
    <Provider store={store}>
      <GestureHandlerRootView style={{ flex: 1 }}>
        <BottomSheetModalProvider>
          <ActionSheetProvider>
            <NavigationContainer headerMode="none">
              <Main hideSplashScreen={onLayoutRootView} />
            </NavigationContainer>
          </ActionSheetProvider>
        </BottomSheetModalProvider>
      </GestureHandlerRootView>
    </Provider>
  );
}

hideSplashScreen passed to <Main hideSplashScreen={onLayoutRootView} /> component and down to the router. There it bing called after auth isLoggedIn state become defined (isLoggedIn !== null). I did it to prevent show LoginScreen before posts screen in a case user has been authorized already.

router.js

export const UseRoute = ({ hideSplashScreen, isLoggedIn }) => {
  if (isLoggedIn !== null) {
    hideSplashScreen();
    if (!isLoggedIn) {
      return (
          <AuthStack.Navigator
            initialRouteName={SCREEN.AUTH.LOGIN}
            screenOptions={{
              headerShown: false,
            }}
          >
            <AuthStack.Screen name={SCREEN.AUTH.LOGIN}>
              {(props) => <LoginScreen {...props} />}
            </AuthStack.Screen>
            <AuthStack.Screen name={STACK.REGISTRATION}>
              {(props) => <RegistrationScreen {...props} />}
            </AuthStack.Screen>
          </AuthStack.Navigator>
      );
    }
    ...

To avoid white screen between Splash and Login or Posts screen I'd made use 2 sec delay before SplashScreen hiding:

App.js

const onLayoutRootView = useCallback(async () => {
  if (fontsLoaded) {
    await delay(
      () =>
        StatusBar.pushStackEntry({
          barStyle: 'dark-content',
          translucent: true,
          animated: true,
          backgroundColor: 'transparent',
        }),
      2000 // 2 sec delay for loading and render data
    );
    delay(SplashScreen.hideAsync, 33); // hide SplashScreen one frame after StatusBar gets translucent
  }
}, [fontsLoaded]);

if (!fontsLoaded) {
  return null;
}

I make use of delay function for delayed execution of callback passed to it.

delay.js

export const delay = (fun, timeout) =>
  new Promise((resolve) => setTimeout(resolve, timeout))
    .then(fun)
    .catch((e) => console.log(e.message));
Clone this wiki locally