Gaurav Singhal Guarav is a data scientist with a strong background in computer science and mathematics. As a developer, he works with Python, Java, Django, HTML, Struts, Hibernate, Vaadin, Web Scrapping, Angular, and React.

Creating custom buttons in React Native

5 min read 1564

Creating Custom Buttons in React Native

React Native is an excellent framework for building native mobile applications. It allows you to build apps that will work on both iOS and Android platforms. Core UI components such as <Button /> look different on each platform, and there are limited styling and customization options (the official React Native docs admit as much).

For this and many other reasons, it’s critical to know how to create buttons that look consistent regardless of the operating system. In this guide, we’ll walk you through how to create various types of custom buttons in React Native.

Setting up your project

Run the following command to get started.

npx react-native init CustomButtonDemo

Remove all the boilerplate code from the App.js file and add the following.

import React from "react";
import { View, Button, StyleSheet } from "react-native";

const App = () => {
  return (
    <View style={styles.screenContainer}>
      <Button title="Hey there!" />
    </View>
  );
};

const styles = StyleSheet.create({
  screenContainer: {
    flex: 1,
    justifyContent: "center",
    padding: 16
  }
});

export default App;

In the above code block, a core <Button /> component is declared and wrapped inside a container. StyleSheet, is an API provided by the React Native framework as an abstraction to CSS StyleSheets.

The custom button component

Now that you’ve set up the main screen, it’s time to turn your attention to the custom button component.

const AppButton = props => (
    // ...
)

Name the custom button component AppButton.

Import the <TouchableOpacity /> and <Text /> components from react-native.

import { View, Button, StyleSheet, TouchableOpacity, Text } from "react-native";

To create custom buttons, you need to customize the <TouchableOpacity /> component and include the <Text /> component inside of it to display the button text.

const AppButton = ({ onPress, title }) => (
  <TouchableOpacity onPress={onPress} style={styles.appButtonContainer}>
    <Text style={styles.appButtonText}>{title}</Text>
  </TouchableOpacity>
);

Next, create the StyleSheet properties to style the button.

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

const styles = StyleSheet.create({
  // ...
  appButtonContainer: {
    elevation: 8,
    backgroundColor: "#009688",
    borderRadius: 10,
    paddingVertical: 10,
    paddingHorizontal: 12
  },
  appButtonText: {
    fontSize: 18,
    color: "#fff",
    fontWeight: "bold",
    alignSelf: "center",
    textTransform: "uppercase"
  }
});

The custom button should look like this:

Custom Button

<TouchableOpacity />, as the name suggests, is a touchable component, which means it can respond to the user’s touch. When you press the button, the opacity decreases. You can control the opacity by passing an activeOpacity prop to the <TouchableOpacity /> component.

const AppButton = ({ onPress, title }) => (
  <TouchableOpacity
    activeOpacity={0.8}
    onPress={onPress}
    style={styles.appButtonContainer}
  >
    <Text style={styles.appButtonText}>{title}</Text>
  </TouchableOpacity>
);

If you want to change the opacity for all the custom buttons in your app, use the defaultProps property. defaultProps is a property in a React component that sets default values for the prop argument.

After you’ve imported TouchableOpacity, add the following line at the top of the file.

TouchableOpacity.defaultProps = { activeOpacity: 0.8 };

The onPress props expect a function or a function reference that will execute when the user presses the button.

The full code for this section is as follows.

import React from "react";
import { View, Button, StyleSheet, TouchableOpacity, Text } from "react-native";

TouchableOpacity.defaultProps = { activeOpacity: 0.8 };

const AppButton = ({ onPress, title }) => (
  <TouchableOpacity onPress={onPress} style={styles.appButtonContainer}>
    <Text style={styles.appButtonText}>{title}</Text>
  </TouchableOpacity>
);

const App = () => {
  return (
    <View style={styles.screenContainer}>
      <AppButton title="Hey there!" size="sm" backgroundColor="#007bff" />
    </View>
  );
};

const styles = StyleSheet.create({
  screenContainer: {
    flex: 1,
    justifyContent: "center",
    padding: 16
  },
  appButtonContainer: {
    elevation: 8,
    backgroundColor: "#009688",
    borderRadius: 10,
    paddingVertical: 10,
    paddingHorizontal: 12
  },
  appButtonText: {
    fontSize: 18,
    color: "#fff",
    fontWeight: "bold",
    alignSelf: "center",
    textTransform: "uppercase"
  }
});

export default App;

Adding more props

Since it’s a custom button component, you have the liberty of piling on additional props. For example, you can add a prop to change the button size or change the background color.

const AppButton = ({ onPress, title, size, backgroundColor }) => (
  <TouchableOpacity
    onPress={onPress}
    style={[
      styles.appButtonContainer,
      size === "sm" && {
        paddingHorizontal: 8,
        paddingVertical: 6,
        elevation: 6
      },
      backgroundColor && { backgroundColor }
    ]}
  >
    <Text style={[styles.appButtonText, size === "sm" && { fontSize: 14 }]}>
      {title}
    </Text>
  </TouchableOpacity>
);

// ...
<AppButton title="Hey there!" size="sm" backgroundColor="#007bff" />;

You’ll see the following result on your screen.

Custom Button With Additional Props

Linear gradient background

By default, React Native doesn’t have an API to create a linear gradient background in a container. Luckily, there’s another utility library for React Native that you can use to create linear gradient colors.

Run the following command to include the library in your project.

npm i react-native-linear-gradient

Next, import the <LinearGradient /> component from the react-native-linear-gradient library.

import LinearGradient from "react-native-linear-gradient";

You ‘ll need to make some adjustments in the <AppButton /> component. Wrap the <TouchableOpacity /> component around the <LinearGradient /> component and add the style prop to the <LinearGradient /> component.

const AppButton = ({ onPress, title }) => (
  <TouchableOpacity onPress={onPress}>
    <LinearGradient
      colors={["#004d40", "#009688"]}
      style={styles.appButtonContainer}
    >
      <Text style={styles.appButtonText}>{title}</Text>
    </LinearGradient>
  </TouchableOpacity>
);

The colors prop in LinearGradient accepts an array, which contains the color values that will be used to create the linear gradient.

Custom Button With Gradient Background

You can learn more about the linear gradient library on GitHub.

Check out the complete code for this section below.

import React from "react";
import { View, Button, StyleSheet, TouchableOpacity, Text } from "react-native";
import LinearGradient from "react-native-linear-gradient";

TouchableOpacity.defaultProps = { activeOpacity: 0.8 };

const AppButton = ({ onPress, title }) => (
  <TouchableOpacity onPress={onPress}>
    <LinearGradient
      colors={["#004d40", "#009688"]}
      style={styles.appButtonContainer}
    >
      <Text style={styles.appButtonText}>{title}</Text>
    </LinearGradient>
  </TouchableOpacity>
);

const App = () => {
  return (
    <View style={styles.screenContainer}>
      <AppButton title="Hey there!" size="sm" backgroundColor="#007bff" />
    </View>
  );
};

const styles = StyleSheet.create({
  screenContainer: {
    flex: 1,
    justifyContent: "center",
    padding: 16
  },
  appButtonContainer: {
    elevation: 8,
    borderRadius: 10,
    paddingVertical: 10,
    paddingHorizontal: 12
  },
  appButtonText: {
    fontSize: 18,
    color: "#fff",
    fontWeight: "bold",
    alignSelf: "center",
    textTransform: "uppercase"
  }
});

export default App;

Controlling button styles using state

As in any React application, you can add styles to your component based on the current value of the state. For example, if you want to disable a button for a certain period of time after it’s pressed, the button must have a disabled background color so that the user knows it’s temporarily inactive.

Add a style property inside the StyleSheet object to represent the disabled color. For this example,  we’ll use black.

const styles = StyleSheet.create({
  // ...
  appButtonDisabled: {
    backgroundColor: "#000"
  }
});

Next, refactor the <AppButton /> component and use the useState hook to change the disabled state.

const AppButton = ({ title }) => {
  const [isDisabled, setDisabled] = useState(false);

  const handlePress = () => {
    setDisabled(true);
    setTimeout(() => setDisabled(false), 3000);
  };

  return (
    <TouchableOpacity
      onPress={handlePress}
      style={[
        styles.appButtonContainer,
        isDisabled && styles.appButtonDisabled
      ]}
      disabled={isDisabled}
    >
      <Text style={styles.appButtonText}>{title}</Text>
    </TouchableOpacity>
  );
};

You can pass a disabled prop to the TouchableOpactiy component to disable the onPress behavior. You can pass an array of style objects to the style prop. So when isDisabled is set to true, you can add the appButtonDisabled property to the style prop array using the && operator.

Styling the button using styled-components

styled-component is a CSS-in-JS library that enables you to write each component with its own style and encapsulate the code in a single location.

React Native follows a certain specification for styling these components. For example, all CSS property names must be written in camelCase — background-color should be specified as backgroundColor, border-width as borderWidth, etc.

This can be a little disorienting for a developer who is approaching mobile app development from a web development background. The styled-components library enables you to write native CSS for styling a React Native component. Under the hood, styled-components simply converts the CSS text into a React Native StyleSheet object.

Run the following command to install styled-components.

yarn add styled-components

Importing the library.

import styled from "styled-components";

Refactor the code to implement styled-components.

Replace the TouchableOpacity and Text components with ButtonContainer and ButtonText, respectively. These new components will be created using the syntax from styled-components.

const AppButton = ({ onPress, title }) => (
  <ButtonContainer onPress={onPress}>
    <ButtonText>{title}</ButtonText>
  </ButtonContainer>
);

styled-components uses tagged template literals to style the components using backticks (`). Each styled component must have a React Native component attached to it.

const ButtonContainer = styled.TouchableOpacity``;

const ButtonText = styled.Text``;

Inside the backticks, add your CSS rules.

const ButtonContainer = styled.TouchableOpacity`
  elevation: 8;
  border-radius: 10px;
  padding-vertical: 10px;
  padding-horizontal: 12px;
`;

const ButtonText = styled.Text`
  font-size: 18;
  color: #fff;
  font-weight: bold;
  align-self: center;
  text-transform: uppercase;
`;

Putting everything together, your code should look like this:

import React from "react";
import { View, Button, TouchableOpacity, Text } from "react-native";
import styled from "styled-components";

TouchableOpacity.defaultProps = { activeOpacity: 0.8 };

const ButtonContainer = styled.TouchableOpacity`
  elevation: 8;
  border-radius: 10px;
  padding-vertical: 10px;
  padding-horizontal: 12px;
`;

const ButtonText = styled.Text`
  font-size: 18;
  color: #fff;
  font-weight: bold;
  align-self: center;
  text-transform: uppercase;
`;

const AppButton = ({ onPress, title }) => (
  <ButtonContainer onPress={onPress}>
    <ButtonText>{title}</ButtonText>
  </ButtonContainer>
);

const App = () => {
  return (
    <View style={styles.screenContainer}>
      <AppButton title="Hey there!" size="sm" backgroundColor="#007bff" />
    </View>
  );
};

export default App;

Conclusion

As a developer, you must build UI components to match whatever reference or design your design team comes up with. It’s your responsibility to make the UI components look precisely as they’re outlined in your client’s plan or prototype.

There’s so much more you can do, but the steps in this guide will help you find your footing as you start creating custom UI components with React Native.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Gaurav Singhal Guarav is a data scientist with a strong background in computer science and mathematics. As a developer, he works with Python, Java, Django, HTML, Struts, Hibernate, Vaadin, Web Scrapping, Angular, and React.

Leave a Reply