Clayton Francis Entrepreneur, software developer, and avid learner. Let’s share the knowledge!

React Native icons and fonts with react-native-vector-icons

6 min read 1712

React Native Icons and Fonts

When it comes to UI/UX, fonts and icons matter. Icons serve as a visual aid for users to navigate your app, and your choice of font (and font color) sets the tone for your app or brand.

Let’s be real: you’d be unlikely to purchase life insurance from a company that uses a cartoonish font such as Alloy Ink or Vegan Style in its contracts. And I couldn’t imagine an app without any icons. Seriously, if you know of one in the App Store, drop me a comment with a link — I’m curious!

In this React Native tutorial, we’ll show you how to:

React Native Fonts and Icons: Example App

The full source code associated with this demo is available on GitHub.

Creating a React Native project

To initialize a React Native project, paste the following into your terminal:

npx react-native init yourAppNameHere --template react-native-template-typescript && cd yourAppNameHere

This will create a new React Native project with a TypeScript template. Navigate to the project folder.

The next step is to build our app for each OS. First, iOS:

yarn run ios 

Now, for Android:

yarn run android

React Native Asset

As software developers, anything that improves our workflow is a welcome change. React Native Asset makes linking and unlinking more straightforward than using react-native link.

We made a custom demo for .
No really. Click here to check it out.

First, install react-native-asset globally:

yarn global add react-native-asset

In your project folder, create a new folder called assets, then create another folder inside it called fonts. Or you can use the terminal:

mkdir -p asset/fonts

Head over to Google Fonts to download the font family. For this example, we’re going with Nunito, but feel free to diverge with a font of your choice.

Once you’ve downloaded the file, unzip it and add your chosen font weights to the fonts folder:

Nunito in Google Fonts

Now, create a new file in your project folder called react-native.config.js:

touch react-native.config.js

Then add the following:

module.exports = {
  assets: ['./assets/fonts'],
};

Finally, use React Native Asset to link the font files. Type the following in your terminal:

react-native-asset

If you need to remove and unlink a font, simply delete it from the fonts folder, then run react-native-asset again. Simple as that.

Creating a text component in React Native

Let’s create a custom text component to consume our new fonts. Create a folder called components with a file inside called Text.tsx, then add the following code:

import React from 'react';
import {
  Text as ReactText,
  StyleSheet,
  StyleProp,
  TextStyle,
} from 'react-native';

type TextProps = {
  children: React.ReactNode;
  style?: StyleProp<TextStyle>;
};

export const Text = ({style, children}: TextProps) => {
  return <ReactText style={[styles.font, style]}>{children}</ReactText>;
};

const styles = StyleSheet.create({
  font: {
    fontFamily: 'Nunito-Regular',
  },
});

The above code creates a Text component with a font-family of Nunito and a regular font-weight that we can use across our app. We get the children and style types (TextProps) from React Native.

Now that we have our Text component, let’s use it!

Replace your App.tsx file with the following:

import React from 'react';
import {SafeAreaView, StyleSheet, StatusBar} from 'react-native';
import {Text} from './components/Text';

const App = () => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView style={styles.container}>
        <Text>This font-weight is 'regular' </Text>
        <Text style={styles.boldFont}>This font-weight is 'bold' </Text>
      </SafeAreaView>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  boldFont: {
    fontFamily: 'Nunito-Bold',
  },
});

export default App;

Notice that we have two different font-weights. Our Text component on line 11 has a bold font-weight. To achieve this, override the font-weight settings with a bold font using StyleSheet.create (line 23), then pass the value to the style prop in the Text component.

React Native font-weight Example

React Native Vector Icons

With nearly 13,000 free icons and 14.5k GitHub stars, React Native Vector Icons is an excellent choice for all your icon needs. Many popular UI libraries, such as Magnus UI, React Native Paper, and React Native Elements, use React Native Vector Icons, so you’re in good company! And if you don’t find what you’re looking for, you can even make your own icons.

To use this package you need to install it. Head over to your terminal and type:

yarn add react-native-vector-icons && yarn add -D @types/react-native-vector-icons && cd ios && pod install && cd ..

This will install the library and dev dependency. Navigate to your iOS folder, install your project’s CocoaPods, then navigate back to your project folder.

Building an icon component in React Native

Now we’re going to build a reusable icon component.

In your components folder, create a new file called Icon.tsx:

cd components && touch Icon.tsx && cd ..

Then, add the following code:

import React from 'react';
import MIcon from 'react-native-vector-icons/MaterialCommunityIcons';

MIcon.loadFont();

type IconSizeProps = {
  iconSizes: keyof typeof IconSizes;
};

export interface IconProps {
  size: IconSizeProps['iconSizes'];
  name: string;
  color: string;
}

export const IconSizes = {
  small: 13,
  medium: 18,
  large: 23,
  extraLarge: 27,
};

export const MaterialIcon = ({size, name, color}: IconProps) => (
  <MIcon name={name} size={IconSizes[size]} color={color} />
);

For each icon bundle you want to use, import and load it as we have in line 2 (import Material Community Icons bundle set) and line 4 (load the icon bundle).

Loading the icons this way eliminates the need to add any native code to use them.

We can export the components with three props that allow us to control the color, size, and type of icon:

  • size is predefined by IconSizes
  • name defines the icon type
  • color defines the icon color

If you’re new to TypeScript and you’re wondering what’s happening on line 7 and 11, hover over iconSizes and you’ll see this:

React Native and TypeScript: IconSizes Example

keyof

In TypeScript, you can create types from JavaScript values. The [keyof](https://www.typescriptlang.org/docs/handbook/2/keyof-types.html) operator takes an object type (IconSizes on line 16) and returns a string or literal union of its keys:

iconSizes: string | number | symbol 

typeof

TypeScript’s version of typeof returns the types of the value of an object:

 iconSizes: {
    small: number;
    medium: number;
    large: number;
    extraLarge: number;
}

keyof typeof

keyof typeof indexes the keys of the object and returns a union of literal types:

iconSizes: "small" | "medium" | "large" | "extraLarge"

Now, thanks to the power of TypeScript, every time you use the size prop, your IDE will know what value should be provided and will display the options for you. To access autocomplete in VSCode on Mac, press ctrl and spacebar together.

Enabling Autocomplete in VS Code

Let’s head back over to App.tsx to test our new Icon component.

import React from 'react';
import {SafeAreaView, StyleSheet, StatusBar} from 'react-native';
import {Text} from './components/Text';
// Import our icon component
import {MaterialIcon} from './components/Icon';

const App = () => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView style={styles.container}>
        <Text>This font-weight is 'regular' </Text>
        <Text style={styles.boldFont}>This font-weight is 'bold' </Text>
        {/* Add icons here */}
        <MaterialIcon size="large" color="purple" name="home" />
        <MaterialIcon size="extraLarge" color="black" name="github" />
      </SafeAreaView>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  boldFont: {
    fontFamily: 'Nunito-Bold',
  },
});

export default App;

For demonstration purposes, I’ve added a home icon and the GitHub logo below the text with different sizes and colors.

React Native Example App With Icons

Creating an icon button component

Buttons look great with icons, so let’s make one. For our button component, we’ll use the custom font that we built earlier with a new icon bundle.

In your components folder, create a new file called IconButton.tsx:

cd components && touch IconButton.tsx && cd ..

Add the following code:

import React from 'react';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
import {Text} from './Text';
import {IconSizes, IconProps} from './Icon';

FontAwesomeIcon.loadFont();

type IconButtonProps = IconProps & {
  text: string;
  onPress: () => void;
};

export const IconButton = ({
  onPress,
  size,
  name,
  color,
  text,
}: IconButtonProps) => (
  <FontAwesomeIcon.Button
    onPress={onPress}
    name={name}
    size={IconSizes[size]}
    color={color}>
    <Text>{text}</Text>
  </FontAwesomeIcon.Button>
);

If we want to use an icon from Material-UI Community Icons, we can import and use the icon component we built already. But this time, we’re going with Font Awesome’s icon bundle set, so we need to load the new icon bundle (line 6).

Now, let’s import our IconButton into App.tsx:

import React from 'react';
import {SafeAreaView, StyleSheet, StatusBar} from 'react-native';
import {Text} from './components/Text';
// Import our icon component
import {MaterialIcon} from './components/Icon';
// Import our icon button component
import { IconButton } from './components/IconButton';

const App = () => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView style={styles.container}>
        <Text>This font-weight is 'regular' </Text>
        <Text style={styles.boldFont}>This font-weight is 'bold' </Text>
        {/* Add icons here */}
        <MaterialIcon size="large" color="purple" name="home" />
        <MaterialIcon size="extraLarge" color="black" name="github" />
        {/* Add icon button here */}
          <IconButton
          onPress={() => {}}
          color="white"
          size="extraLarge"
          name="facebook"
          text="Login in with Facebook"
        />
      </SafeAreaView>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  boldFont: {
    fontFamily: 'Nunito-Bold',
  },
});

export default App;

As with the MaterialIcon component we built earlier, you can set the color, size, and icon type with the provided props.

React Native Icon Component Example

Conclusion

It’s worth perusing the icons at the design stage of your app; there are some real gems in the icon bundle sets. If you’re looking for something specific, you should try lots of similar, descriptive keywords. For example, a search for “settings” will return a cog icon, but if you want an icon with multiple cogs, try searching “cogs.”

React Native Icon Search

React Native Icon Search

Now that you know how to customize your font, don’t be afraid to extend your text component with a nice font pairing — e.g., Nunito for headers and Roboto for paragraphs:

React Native Example App With Nunito and Roboto Fonts

There you have it! You can customize your fonts and add icons to your heart’s content. Now go forth and build something amazing — just don’t use Vegan Style if you’re selling life insurance!

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Clayton Francis Entrepreneur, software developer, and avid learner. Let’s share the knowledge!

Leave a Reply