Learn to create a custom progress button in React Native and TypeScript

How to create a custom progress button in React Native with TypeScript:

In this post, I will show you how to create a custom progress button in React Native using TypeScript. We will create a button component that will take different props to customize its style.

props of the button:

The following interface will be used as the button props:

interface LoadingButtonProps {
  backgroundColorDefault: string;
  backgroundColorLoading: string;
  isLoading: boolean;
  indicatorColor: string;
  indicatorSize: number | "small" | "large" | undefined;
  textColorDefault: string;
  textColorLoading: string;
  text: string;
  textLoading: string;
  fontSize: number;
  width: number;
  height: number;
  borderRadius: number;
  onPress: () => void;
}

Here,

  • backgroundColorDefault is the default color for the button.
  • backgroundColorLoading is the color of the button on the loading state.
  • isLoading defines the current state.
  • indicatorColor is the color of the activity indicator.
  • indicatorSize is the size of the activity indicator.
  • textColorDefault is the default font color.
  • textColorLoading is the font color when the button is loading.
  • text is the default text.
  • textLoading is the text to show on loading.
  • fontSize is the font size.
  • width is the width of the button.
  • height is the height of the button.
  • borderRadius is the border radius of the button.
  • onPress is a callback method to invoke when user taps on the button.

Button component:

Let’s create one new component LoadingButton.tsx with the following code:

import React from "react";
import { Pressable, View, Text, ActivityIndicator } from "react-native";

interface LoadingButtonProps {
  backgroundColorDefault: string;
  backgroundColorLoading: string;
  isLoading: boolean;
  indicatorColor: string;
  indicatorSize: number | "small" | "large" | undefined;
  textColorDefault: string;
  textColorLoading: string;
  text: string;
  textLoading: string;
  fontSize: number;
  width: number;
  height: number;
  borderRadius: number;
  onPress: () => void;
}

const LoadingButton = (props: LoadingButtonProps) => {
  return (
    <Pressable onPress={props.onPress}>
      <View
        style={{
          backgroundColor: props.isLoading
            ? props.backgroundColorLoading
            : props.backgroundColorDefault,
          width: props.width,
          height: props.height,
          borderRadius: props.borderRadius,
          alignItems: "center",
          justifyContent: "center",
          flexDirection: "row",
        }}
      >
        {props.isLoading && (
          <ActivityIndicator
            size={props.indicatorSize}
            style={{ paddingEnd: 10 }}
            color={props.indicatorColor}
          />
        )}
        <Text
          style={{
            color: props.isLoading
              ? props.textColorLoading
              : props.textColorDefault,
            fontSize: props.fontSize,
          }}
        >
          {props.isLoading ? props.textLoading : props.text}
        </Text>
      </View>
    </Pressable>
  );
};

export default LoadingButton;

This is the loading button.

  • It uses a Pressable as its parent component.
  • The visibility of the ActivityIndicator is controlled by the isLoading value of the props. Other styles are added as defined by the props to the components.

App.tsx file changes:

We can use the above component in any other component. For example, the following code uses the LoadingButton component:

import React, { useState } from "react";
import { SafeAreaView, StyleSheet } from "react-native";
import LoadingButton from "./LoadingButton";

const App = () => {
  const [loading, setLoading] = useState(false);

  const onPressButton = () => {
    setLoading(!loading);
  };

  return (
    <SafeAreaView style={styles.container}>
      <LoadingButton
        backgroundColorDefault="#6750A4"
        backgroundColorLoading="#79747E"
        isLoading={loading}
        indicatorColor="white"
        indicatorSize={26}
        textColorDefault="white"
        textColorLoading="white"
        text="Download"
        textLoading="Downloading.."
        fontSize={20}
        width={300}
        height={60}
        borderRadius={10}
        onPress={onPressButton}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
});

export default App;

Output:

The state of the button is changed on clicking on it. If you run it on Android device, it will look as below:

React Native custom progress button

You might also like: