Create a reusable text component in React native


Jul 05, 2022 | React Native

If you are learning React and React Native, most likely you are familiar with the concept of a component, and you probably have created some for your project.

Your app is probably using headers and paragraphs all over your app. And, you are probably using the Text component from React Native directly for all of them.
This is fine, until you have to change something on all headers or paragraphs - for example, text colour. Now you have many many places where you have to do this change.

Wouldn't you want to be able to update the colour once and changes get applied across the app?
One way to solve this is by using a global stylesheet. The downside of this approach is that this global stylesheet can grow into a gigantic monster, and it doesn't really provide a clean way of setting other props, like font weight, font size, etc. You would have to mix a few styles together to get the desired result.

Reusable text component to the rescue

A reusable text component can give you all the flexibility you need to have everything defined in one place, and reused across the app. Let's build one.

Step 1: Where to put it?

My approach is simple, in the App directory (or root, depending on your app structure) I create a folder called components.
I also add an index.ts file where I manage all my imports and exports.

Step 2: The basic component

Let's create our basic Text component first, and we will extend it later.

import React, { ReactNode } from "react";
import { Text as GenericText } from "react-native";

interface Props {
  children: ReactNode;
}

const Text = ({ children }: Props) => {
  return (
    <GenericText>
      {children}
    </GenericText>
  )
}

export default Text;

Lets also update our index.ts:

import Text from "./Text";

export { Text }

This will allow us to import the component from other places like this:

import { Text } from "../components";
Step 3: What are your requirements?

You should create this component with your current requirements in mind. Do not create something that you don't have the need for yet, as you might never need it. If you are working with a designer and they provide you with a design file (ex: Figma), everything you need to know about this text component is there: text size, colours, margins, paddings, weight, etc.

If you don't have any designs, my rule is to think about what is that I need right now. Usually, those are h1 and h2 headers, and paragraph text. That's it.

Let's create h1, h2 and paragraph styles, and you can use this a starting point to extend it and adapt it to your needs.

First, we will need a way to define styles. To do so, let's import StyleSheet from react native:

import React, { ReactNode } from "react";
import { Text as GenericText, StyleSheet } from "react-native";

...

Next, we need to think about different ways we want to use this component. For example, do you want to specify different props that will set appropriate styles, or do you want to pass styles, or something completely different.

My approach is like this:

  • I want to have component defaults so I don't have to specify exactly what I want every time I want to use it (usually, that is the paragraph type);
  • I want to be able to set font weight as a prop;
  • I want to be able to override styles if I want to;

And that's it. Here are some examples of how I want to use it:

// ...some other place
import { Text } from "../components";
...
<Text>I'm a paragraph</Text>
<Text p>I'm also a paragraph</Text>
<Text h1>I'm H1</Text>
<Text h2>I'm H1</Text>
<Text h2 weight="700">I'm H1</Text>
...
Step 4: Creating the actual component (full example)
import React, { ReactNode } from "react";
import { Text as GenericText, StyleSheet, TextStyle } from "react-native";

interface Props {
  children: ReactNode;
  h1?: boolean;
  h2?: boolean;
  p?: boolean;
  style?: object;
  props?: any;
};

const Text = ({ 
  children,
  h1,
  h2,
  p,
  weight,
  style,
  ...props
}: Props) => {
  const textStyles = StyleSheet.flatten([
    styles.defaults,
    h1 && { fontSize: 26, fontWeight: "700" },
    h2 && { fontSize: 22, fontWeight: "700" },
    p && { fontSize: 16, fontWeight: "500" },
    weight !== undefined && { fontWeight: weight },
    style
  ]);

  return (
    <GenericText style={textStyles as TextStyle} {...props}>
      {children}
    </GenericText>
  )
}

const styles = StyleSheet.create({
  defaults: {
    fontSize: 16,
    fontWeight: "500",
    color: "#000"
  },
})

export default Text;