(React Native) Create a Custom Text Component with Custom font-family
Today, I am going to share my knowledge to create a handy reusable custom text component in React Native. The final source code is available on my Github.
Prerequisites
- I will be using Typescript in this article
- The project is generated using pure React Native
- Basic knowledge of pure React Native development
My Environment
- React Native: 0.61.5
- macOS Catalina: Version 10.15.2 (19C57)
- Typescript: 3.7.4
1. Generate and setup a React Native project
First, generate a new React Native project with the following code.
react-native init CustomTextExample
Next, add the necessary dependencies.
// Add typescript
npm i -D typescript react-native-typescript-transformer// Add eslint with typescript plugin
npm i -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin// Add types
npm i -D @types/react @types/react-native// Optionally, you can add prettier
npm i -D prettier eslint-config-prettier eslint-plugin-prettier
Then, modify the .eslinttrc.js
file something like below to configure Typescript stuff.
// .eslinttrc.jsmodule.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018, // Allow to parse modern ECMAScript features
sourceType: 'module', // Allow to use imports
ecmaFeatures: {
jsx: true,
},
},
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'prettier',
'prettier/@typescript-eslint',
],
rules: {
semi: 0,
'ordered-imports': 0,
'object-literal-sort-keys': 0,
'member-ordering': 0,
'jsx-no-lambda': 0,
'jsx-boolean-value': 0,
'no-console': 0,
'no-empty-interface': 0,
'interface-name': [0, 'always-prefix'],
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-function-return-type': [
'warn',
{
'allowExpressions': 1,
'allowTypedFunctionExpressions': 1
}
]
},
env: {
es6: true,
node: true,
}
}
Finally, rename the App.js
and index.js
files to App.tsx
and index.ts
. Also, create the src
folder at the root directory and move the App.tsx
file in the src
directory. After moving the App.tsx
file, don’t forget to also modify the directory in the index.ts
file.
At this point, you might have some typing errors. We will fix those errors later when we create the CustomText component, so just ignore those errors for now.
That’s everything for the setup.
2. Download Google Fonts
Next, we need the font to use it in the app. Go to the Google Fonts website and download any font that you want to use. All you need to do here is to search for a font and click on the download icon at the top-right of the modal. I use ‘Lato’ for this tutorial.
After downloading the font, we need to configure the font to use it in the app. Under the root directory of the app, create the /src/assets/fonts/
directory and put your font files there.
Then, at the root directory of the app, create the file named react-native.config.js
and paste the code below.
// react-native.config.jsmodule.exports = {
assets: ['./src/assets/fonts'],
}
Finally, run the following code on your terminal.
react-native link
Now, our app should recognize the downloaded font.
3. Create the CustomText component
Now, it’s time to create the CustomText component. Under the src
directory, create the components
folder. Inside the components
folder, create the file and name it CustomText.tsx
. Then, add the boilerplate below.
// CustomText.tsximport React, { FunctionComponent } from 'react'
import {
Text,
StyleSheet
} from 'react-native'type CustomTextProps = {}const CustomText: FunctionComponent<CustomTextProps> = ({ children }) => {
return (
<Text>
{children}
</Text>
)
}const styles = StyleSheet.create({})export default CustomText
4. Make the font family configurable
To make the font family configurable via props, make the following changes to the component.
// CustomText.tsx...type CustomTextProps = {
textType?: 'regular' | 'bold' | 'light'
}const CustomText: FunctionComponent<CustomTextProps> = ({ children, textStyle }) => {
let textStyle: {}
switch (textType) {
case 'regular':
textStyle = styles.regular
break
case 'bold':
textStyle = styles.bold
break
case 'light':
textStyle = styles.light
break
default:
textStyle = styles.regular
break
}return (
<Text style={textStyle}>
{children}
</Text>
)
}const styles = StyleSheet.create({
regular: {
fontFamily: 'Lato-Regular'
},
bold: {
fontFamily: 'Lato-Bold'
},
light: {
fontFamily: 'Lato-Light'
}
})export default CustomText
In the code above, the following changes were made.
- Styles in StyleSheet.create()
Define the font families that you want to have here. textType
prop type
AddtextType
prop type in CustomTextProps type to receive the prop to configure which font family to use. In this case, I can just pass ‘regular’, ‘bold’ or ‘light’ as the value. Don’t forget to addtextType
to destructured props also.- The switch statement
The switch statement is used to assign a font family from thestyles
constant depending on thetextType
prop. I store it into the variable calledtextStyle
and assign it as the style for theText
component inside the return statement.
5. Make the component be able to receive custom styles
To pass custom styles from the parent component, we need a little bit more work. Add the following changes below.
// CustomText.tsximport React, { FunctionComponent } from 'react'
import {
StyleSheet,
Text,
TextStyle
} from 'react-native'type CustomTextProps = {
style?: TextStyle | TextStyle[]
textType?: 'regular' | 'bold' | 'light'
}const CustomText: FunctionComponent<CustomTextProps> = ({ children, textStyle, style }) => {
let textStyle: {}
switch (textType) {
...
}const passedStyles = Array.isArray(style) ? Object.assign({}, ...style) : stylereturn (
<Text style={[textStyle, { ...passedStyles } ]}>
{children}
</Text>
)
}const styles = StyleSheet.create({
...
})export default CustomText
In the code above, the following changes were made.
style
prop type
Import theTextStyle
type from react-native and addstyle?
prop type in CustomTextProps type. Adding?
at the end makes it an optional prop. The type will be either ofTextStyle
orTextStyle[]
. This is because the components in React usually take an object of styles or an array of style objects.- The
passedStyles
constant
If thestyle
prop is passed an array of style objects, we cannot assign the values directly.Object.assign({}, …style)
will spread the values of the passed array and assign it to the empty object. Using the ternary operator, an array is spread into an object if the type of thestyle
prop is an array before it gets stored into thepassedStyles
constant. - Pass both of
textStyle
andpassedStyles
Finally, passpassedStyles
as one of the style prop values.
6. Modify the App.tsx to display CustomText
Finally, modify the App.tsx
file to display our CustomText.
import React, { Component } from 'react'
import {
StyleSheet,
SafeAreaView,
View
} from 'react-native'
import CustomText from './components/CustomText'class App extends Component {
render() {
const { container, customTextStyle } = styles
return (
<SafeAreaView style={container}>
<View>
<CustomText textType='light' style={[customTextStyle, { color: 'blue' }]}>Light</CustomText>
<CustomText textType='regular' style={[customTextStyle, { color: 'red' }]}>Regular</CustomText>
<CustomText textType='bold' style={[customTextStyle, { color: 'green' }]}>Bold</CustomText>
</View>
</SafeAreaView>
)
}
}const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
customTextStyle: {
fontSize: 16,
marginBottom: 8
}
})export default App
If you run the app, you can see that the font families and each text styles are applied properly as the screenshot below.
That’s everything for this article.
Resources:
- ADD A CUSTOM FONT TO YOUR REACT NATIVE APP:
https://blog.bam.tech/developer-news/add-a-custom-font-to-your-react-native-app