White flash / flickering when using expo-font
Thanaen opened this issue · comments
Which package manager are you using? (Yarn is recommended)
npm
Summary
I’m developing an application with a dark and a light theme, and custom fonts.
I’m trying to migrate everything to expo, but I have a problem: I get a white flash when I launch my application.
I did a lot of research to find out what was causing this, and concluded that using expo’s useFont hook could cause the problem.
One solution would be to give a value to the “backgroundColor” property, in the app.json file, but this isn’t a good solution for two reasons:
- only one color can be set, and therefore cannot be adapted to the dark theme (unless you use expo-system-ui with the setBackgroundColor method)
- setting a backgroundColor has a very ugly effect on iOS modals, so it’s best to leave this property undefined.
I’m a bit up against the wall with this problem :(.
Minimal reproducible example
https://github.com/Thanaen/expo-router-font-white-flash
PS: I've also created a forum post for this issue
Any luck?
I haven't managed to solve the problem yet.
I've tried loading my fonts differently (via this library https://github.com/EvanBacon/link-native-assets-expo-config-plugin), but I've run into another bug that causes one of my custom fonts not to load on iOS. :(
Do you use the expo-splash-screen
functions in your app? The docs reference using the package to prevent a white flash with expo-router
: https://docs.expo.dev/routing/appearance/#fonts
This seems to help on the small repro project I've set up, but on my bigger project it doesn't prevent white flash :(
any update @Thanaen? we're facing the same issue :-(
Duplicate #675
Some notes about this issue (for future reference):
- The issue was that useFont (or any hook) would cause a re-render of the layout route, which would unmount the
<SplashScreen />
component, and therefore hide the splash screen prematurely. This SplashScreen-component API was flawed which is why it's been deprecated. - Not using the
SplashScreen
component fixes the issue because the default hiding works. - Alternatively, you can prevent hiding by modifying the root layout file to use the new API. You will need to delay hiding by a frame though:
import { SplashScreen, Stack } from "expo-router";
SplashScreen.preventAutoHideAsync();
const Layout = () => {
const colorScheme = useColorScheme();
let [fontsLoaded] = useFonts({
Inter_900Black,
});
React.useEffect(() => {
if (fontsLoaded) {
setTimeout(() => {
SplashScreen.hideAsync();
});
}
}, [fontsLoaded]);
return (
<ThemeProvider
value={colorScheme === "dark" ? NavDarkTheme : NavDefaultTheme}
>
{fontsLoaded ? (
<Stack>
...
</Stack>
) : null}
</ThemeProvider>
);
};
export default Layout;
I've tested all of these locally and can personally confirm they work.
Thank you for your reply. I'll try the setTimeout trick!
@VirenMohindra
To be honest, I've paused the migration to expo-router for now, as I've encountered regressions related to the switch to expo-prebuild and expo-router that affect the UX. :/
I'll be opening other issues soon, as I fully intend to jump on the expo-prebuild and expo-router bandwagon!