14

I just upgraded to Expo SDK 45 and i got a warning: "expo-app-loading is deprecated in favor of expo-splash-screen: use SplashScreen.preventAutoHideAsync() and SplashScren.hideAsync() instead. https://docs.expo.dev/versions/latest/sdk/splash-screen/. So I did and followed the link provided.

The problem I have now is that in the example they call onLayOutRootView on the onLayOut of the root view. Now I'm using react-navigation so my root view is nested quite deep into my application.

Do I have to pass this function down to the root view or is there a way to pass this function to one of my providers/navigationcontainer? Or any other fix?

//imports


export default App = () => {
  const [appIsReady, setAppIsReady] = useState(false);
  const scheme = "dark";

  useEffect(() => {
    async function prepare() {
      try {
        // Keep the splash screen visible while we fetch resources
        await SplashScreen.preventAutoHideAsync();
        // Pre-load fonts, make any API calls you need to do here
        await Font.loadAsync(customFonts);
      } catch (e) {
        console.warn(e);
      } finally {
        // Tell the application to render
        setAppIsReady(true);
      }
    }

    prepare();
  }, []);

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

  if (appIsReady) {
    return (
      <StripeProvider publishableKey={PUBLISHABLE_KEY}>
        <ThemeProvider theme={scheme === "dark" ? darkTheme : lightTheme}>
          <StatusBar barStyle={scheme === "dark" ? "light-content" : "dark-content"} />
          <OrderProvider>
            <CartProvider>
              <FavoriteProvider>
                <FirebaseProvider>
                  <UserProvider>
                    <NavigationContainer
                      theme={scheme === "dark" ? darkTheme : lightTheme}
                      ref={navigationRef}
                    >
                      <RootStackScreens on/>
                    </NavigationContainer>
                  </UserProvider>
                </FirebaseProvider>
              </FavoriteProvider>
            </CartProvider>
          </OrderProvider>
        </ThemeProvider>
      </StripeProvider>
    );
  } else {
    return null;
  }
};

Thanks.

Bert Van Hecke
  • 211
  • 2
  • 12
  • Hey Bert - having the same issue haha just getting to expo 45. I've just dropped the whole callback. I was getting "SplashScreen.show has already been called" and just hiding the real return behind a if isReady. - i hope someone else has something better to contribute haha – snoop May 27 '22 at 18:55
  • The answer marked works for me :) – Bert Van Hecke May 31 '22 at 10:45

3 Answers3

15

You can try wrap everything in a View with flex:1.

Something like this:

...imports...
import { View } from "react-native";
    
export default App = () => {

 ...code...

 const onLayoutRootView = useCallback(async () => {
  if (appIsReady) {
   await SplashScreen.hideAsync();
  }
 }, [appIsReady]);
    
 if (!appIsReady) {
  return null;
 }
    
 return (
  <View style={{ flex: 1 }} onLayout={onLayoutRootView}>
   <StripeProvider publishableKey={PUBLISHABLE_KEY}>
     ...
   </StripeProvider>
  </View>
 );
}
Manuel
  • 366
  • 2
  • 7
15

As the question uses NavigationContainer, I think the best approach would be to follow expo's instructions, but modify the function's 'return' to pass onLayoutRootView to the NavigationContainer and not to a View, as follows:

return (
...
  <NavigationContainer
    theme={scheme === "dark" ? darkTheme : lightTheme}
    ref={navigationRef}
    onReady={onLayoutRootView} // <-- HERE!
  >
     <RootStackScreens on/>
  </NavigationContainer>
...
)

This answer is based on this code example.

RdC1965
  • 412
  • 5
  • 8
  • Thanks, works like a charm! I think this should be the accepted answer because it is more in line with both the intended use of the navigation package as well as Expo's instructions. – buechel Jul 25 '23 at 10:31
5

Just call set NavigationContainer onReady to onLayoutRootView

 <NavigationContainer onReady={onLayoutRootView}>
    <NavigatorDrawer />
 </NavigationContainer>