In this article, you are going to learn how to add badges to components in React Native for both iOS and Android in your app. You’ll see an easy example of using Higher-Order Components.
Badges are a core feature in both Android and iOS apps. I find myself frequently having to add badges to my UI. But I didn’t discover any library that streamlined adding badges to its components¹.
We are going to change that. You are going to learn how to create a simple Higher-Order Component (HOC) that makes adding badges to components super easy. We are going to be adding badges to list items as well as icons.
Here is a preview of what we are going to build. (Scroll to the bottom of the post to see the full app.)
This tutorial has two parts. In the first part, we are going to create a simple dummy app, so I can show you how to use the HOC in different situations. We will write the HOC in the second part. If you only want to see the code for the HOC, skip to section 2.
1. Building the App
Start by creating a new React Native app.
We will use three packages. React Navigation, React Native Elements and React Native Vector Icons, so we can quickly build a UI. Install and link them.
Note: As of the publishing of this post, React Navigation V3 has been released. The instructions in this tutorial are written with V2. Furthermore, React Native Elements is still in beta and will release its version 1.0.0 soon. Therefore we are going to use the “next” branch.
In your project folder create a folder called app/ (adjacent to your node_modules/). Move the App.js file to this folder and modify index.js to import App from the new location.
Within app/ create four more folders: components/, config/, navigation/ and screens/. (Make sure to create the file for the HOC part, too, in components/.)
Within config/ create a file called fixtures.js and post the following array into it.
We will use this data to display our dummy list. We are going for a basic two tabs layout. Create two files, one for each screen, within screens/ (EmptyScreen.js and ListScreen.js). The first one will be empty and is just there to make our tabs look good².
The second screen contains the list with our dummy items.
We use a simple <FlatList /> here that renders through the data array. Additionally, we add a couple of <Icon />s to the header so that we can badge them up later.
Next, create the navigation routes inside navigation/navigation.js.
Nothing special is going on here. I like to configure my navigators using constants like stackConfig. If your app grows large, it spares you a lot of spaghetti code and lets you change the look of your app in one place.
Lastly, we need to hook up our navigator to the app.
Well done. We are now ready to build the HOC 🙌🏻.
2. a.) Coding the Higher-Order Component
Why do we build a HOC? According to the documentation, “a higher-order component is a function that takes a component and returns a new component”. Consequently, the reason we use a HOC is its flexibility and reusability. Instead of overwriting all components to give them a badge prop, we can wrap it in our HOC.
Create a file within components/ called withBadge.js.
Let’s go through this and understand the code.
First, we define a bunch of styles. These give the component a perfect size and shape for icons while deactivating the badge’s minWidth and the text's padding (otherwise the badge would look deformed).
Afterwards, we define the HOC. It receives two parameters. A value which determines what is displayed within the badge. And an optional options parameter. With options, you can adjust the badges position as well as programmatically hide it using the hidden key³. Lastly, you can add any value that is also a prop for the <Badge /> and it will be spread into the badge.
We wrap the component inside a <View /> tag. Combining this with the position: "absolute" style our badge always has the same reference point for its offset. This wouldn’t be the case if we were to use <React.Fragment />.
Finally, notice the props that we pass <Badge />. Three of these props only work if you correctly use the “next” branch from React Native Elements. Otherwise, there would be no status prop, badgeStyle would be containerStyle, and containerStyle would be wrapperStyle.
That’s it! 👏🏻 Following this, we need to be …
2. b.) Using the Badge
Let’s apply our badge to a couple of components. Start by giving your chat-bubbles icon in the header a badge. To do that we need to import withBadge in hour ListScreen.
Afterwards, we need to modify our navigationOptions to use a function⁴.
We converted our icon to a <BadgedIcon />. Since used a HOC we can just pass the <BadgedIcon /> the same props <Icon /> receives. It’s as easy as that! 😊
Now, let’s give an Avatar of one of the <ListItem />s a green badge. For that, we have to pass status: "success" into options.
We also adjusted the badges position by moving it 25 pixels to the left, so it looks neat on the avatar 👌🏻.
Your turn!
If you coded along, now is your time to shine and be creative. Here is a challenge for you. Give the list icon in the tab bar a badge.
I created a PR for React Native Elements for the HOC of this tutorial. It got accepted and merged ✅. If you are a beginner, check it out. It’s an interesting read. I learned a lot during this PR (special thanks to Kyle ❤️).
Why not use the EmptyScreen after you finished this tutorial to test out code and mess around with the badges? 🎓
If you want to use a MiniBadge you will have to set hidden to false.