Real-Time Font Management in Expo
I’ve cooked up a package that takes the headache out of font management in React Native and Expo. The coolest part? You can switch fonts on the fly, just like changing a CSS rule.
Why is this even a problem?
Adding fonts to React Native apps has always been a headache. It’s a process full of tricky steps: making sure fonts are linked right, putting them in the correct folders, and renaming them properly. Even when you think you’ve done everything right, you might end up confused. Your font might look great on an iPhone but not show up at all on an Android device, or the other way around. This font problem has been a constant source of frustration for developers, often turning a simple task into a real challenge.
What to do about it?
This is where ‘expo-dynamic-fonts’ comes in. To get started with Expo Dynamic Fonts, simply install it using npm:
npm install expo-dynamic-fonts
You’ll also need to download ‘expo-font’
npm install expo-font
Once installed you can easily use any font from Google Fonts with some pretty straightforward methods.
The Text Component
By far the most straightforward way to use this package can be illustrated by the example below
import React from 'react';
import { View } from 'react-native';
import { Text } from 'expo-dynamic-fonts';
const App = () => {
return (
<View className="flex-1 justify-center items-center p-4">
<Text font="Roboto" className="text-2xl mb-4">
This text uses Roboto font
</Text>
<Text font="Open Sans" className="text-lg">
This text uses Open Sans font
</Text>
</View>
);
};
export default App;
The Text component from expo-dynamic-fonts builds on React Native’s standard Text component. It works just like the regular Text you’re used to, but with some extra font-loading abilities. You can use all the usual Text props, plus a new ‘font’ prop for specifying Google Fonts.
The Custom Component
The createFontComponent function creates a new component that wraps the Text component with a specific font.
import React from 'react';
import { View } from 'react-native';
import { createFontComponent } from 'expo-dynamic-fonts';
const RobotoText = createFontComponent('Roboto');
const OpenSansText = createFontComponent('Open Sans');
const App = () => {
return (
<View className="flex-1 justify-center items-center">
<OpenSansText className="text-lg">Hello, Open Sans!</OpenSansText>
<RobotoText className="text-xl mt-4">Hello, Roboto!</RobotoText>
</View>
);
};
export default App;
This allows you to use the custom font component directly, without specifying the font prop each time. This can be useful if you have a certain font you know you’ll use across your app and you don’t want to pass in a font prop each time.
And last but not least, The Hook
This method gives you more control over font loading and allows you to handle loading states manually.
import React from 'react';
import { View, Text as RNText } from 'react-native';
import { useFont } from 'expo-dynamic-fonts';
const App = () => {
const robotoLoaded = useFont('Roboto');
const openSansLoaded = useFont('Open Sans');
if (!robotoLoaded || !openSansLoaded) {
return <View><RNText>Loading fonts...</RNText></View>;
}
return (
<View className="flex-1 justify-center items-center">
<RNText style={{ fontFamily: 'Open Sans' }} className="text-lg">
Hello, Open Sans!
</RNText>
<RNText style={{ fontFamily: 'Roboto' }} className="text-xl mt-4">
Hello, Roboto!
</RNText>
</View>
);
};
export default App;
The useFont hook manages the font loading process. It returns a boolean indicating whether the font has been loaded. You can use this to conditionally render your components or show a loading state. Once the fonts are loaded, you can apply them directly to your text components.
I’ve set up these different ways to use fonts because I know developers have different needs. If you just want to get going quickly, the Text component is your best bet. It’s simple and does the job without any fuss.
But let’s say you’re using a particular font all over your app. That’s where createFontComponent comes in handy. You set it up once, and then you can use that custom component wherever you need that font.
Now, for those of you who like to have everything just so, the useFont hook gives you all the control. You can manage exactly how and when your fonts load, which is great for more complex apps.
The whole point here was to make designing with code easier. I wanted to get rid of all that hassle with font files, making sure the names are exactly right, or messing around with native code. Now you can just focus on making your app look great, without all the font-related headaches.
If you want to checkout the source code, go to the github repo down below.