
上QQ阅读APP看书,第一时间看更新
How to do it...
- With our font files in place, the first step is to open App.js and add the imports we'll need:
import React from 'react'; import { Text, View, StyleSheet } from 'react-native'; import { Font } from 'expo';
- Next, we'll add a simple component for displaying some text that we want to style with our custom fonts. We'll start with just one Text element to display the regular variant of the Roboto font:
export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text style={styles.josefinSans}> Hello, Josefin Sans! </Text> </View> ); } }
- Let's also add some starter styles for the component we've just created. For now, we'll just increase the font size for our josefinSans class styles:
const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, josefinSans: { fontSize: 40, } });
- If we open the app now in our simulator, we will see the Hello, Josefin Sans! text displayed in the middle of the screen using the default font:

- Let's load our JosefinSans-Regular.ttf font file so that we can style our text with it. We'll use the componentDidMount life cycle hook provided by React Native to tell our app when to start loading the font:
export default class App extends React.Component { componentDidMount() { Font.loadAsync({ 'josefin-sans-regular': require('./assets/fonts/JosefinSans-Regular.ttf'), }); } render() { return ( <View style={styles.container}> <Text style={styles.josefinSans}> Hello, Josefin Sans! </Text> </View> ); } }
- Next, we'll add the font we're loading to the styles being applied to our Text element:
const styles = StyleSheet.create({ // Other styles from step 3
josefinSans: { fontSize: 40, fontFamily: 'josefin-sans-regular' } });
- We now have styles, right? Well, not quite. If we look back at our simulators, we'll see that we're getting an error instead:
console.error: "fontFamily 'josefin-sans-regular' is not a system font and has not been loaded through Expo.Font.loadAsync"
- But we did just load fonts via Expo.Font.loadAsync! What gives? It turns out we have a race condition on our hands. The josefinSans styles we defined for our Text element are being applied before the Josefin Sans font has been loaded. To handle this problem, will need to use the component's state to keep track of the load status of the font:
export default class App extends React.Component {
state = { fontLoaded: false };
- Now that our component has a state, we can update the state's fontLoaded property to true once the font is loaded. Using the ES6 feature async/await makes this succinct and straightforward. Let's do this in our componentDidMount code block:
async componentDidMount() { await Font.loadAsync({ 'josefin-sans-regular': require('./assets/fonts/JosefinSans-
Regular.ttf'), }); }
- Since we are now awaiting the Font.loadAsync() call, we can set the state of fontLoaded to true once the call is complete:
async componentDidMount() { await Font.loadAsync({ 'josefin-sans-regular': require('./assets/fonts/JosefinSans-
Regular.ttf'), }); this.setState({ fontLoaded: true }); }
- All that's left to do is to update our render method to only render the Text element that depends on the custom font when the fontLoaded state property is true:
<View style={styles.container}> { this.state.fontLoaded ? ( <Text style={styles.josefinSans}> Hello, Josefin Sans! </Text> ) : null } </View>
- Now, when we check out our app in the simulators, we should see our custom font being applied:

- Let's load the rest of our fonts so that we can use them in our app as well:
await Font.loadAsync({ 'josefin-sans-regular': require('./assets/fonts/JosefinSans-
Regular.ttf'), 'josefin-sans-bold': require('./assets/fonts/JosefinSans-
Bold.ttf'), 'josefin-sans-italic': require('./assets/fonts/JosefinSans-
Italic.ttf'), 'raleway-regular': require('./assets/fonts/Raleway-
Regular.ttf'), 'raleway-bold': require('./assets/fonts/Raleway-Bold.ttf'), 'raleway-italic': require('./assets/fonts/Raleway-
Italic.ttf'), });
- We'll also need Text elements for displaying text in each of our new font families/variants. Note that we'll also need to wrap all our Text elements in another View element, since JSX expressions require that there be only one parent node. We're also now passing the style property an array of styles to apply in order to consolidate the fontSize and padding styles we'll be applying in the next step:
render() { return ( <View style={styles.container}> { this.state.fontLoaded ? ( <View style={styles.container}> <Text style={[styles.josefinSans,
styles.textFormatting]}> Hello, Josefin Sans! </Text> <Text style={[styles.josefinSansBold,
styles.textFormatting]}> Hello, Josefin Sans! </Text> <Text style={[styles.josefinSansItalic,
styles.textFormatting]}> Hello, Josefin Sans! </Text> <Text style={[styles.raleway, styles.textFormatting]}> Hello, Raleway! </Text> <Text style={[styles.ralewayBold,
styles.textFormatting]}> Hello, Raleway! </Text> <Text style={[styles.ralewayItalic,
styles.textFormatting]}> Hello, Raleway! </Text> </View> ) : null } </View> ); }
- All that's left to apply our custom fonts is to add the new styles to the StyleSheet:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
josefinSans: {
fontFamily: 'josefin-sans-regular',
},
josefinSansBold: {
fontFamily: 'josefin-sans-bold',
},
josefinSansItalic: {
fontFamily: 'josefin-sans-italic',
},
raleway: {
fontFamily: 'raleway-regular',
},
ralewayBold: {
fontFamily: 'josefin-sans-bold'
},
ralewayItalic: {
fontFamily: 'josefin-sans-italic',
},
textFormatting: {
fontSize: 40,
paddingBottom: 20
}
});
- Now, in our app, we'll see six different text elements, each styled with its own custom font:
