Crafting a Custom Button Component in React Native
Tags: reactnative, react, android, ios
Published: 2024-01-28 18:46:26

## Introduction

_React Native_, a powerful framework for building native apps for _iOS_ and _Android_ using _JavaScript_, often requires developers to create custom UI components, like a custom button. This article will guide you through creating a custom button in React Native, focusing on different touchable components and explaining why `Pressable` might be a preferable choice.

### Differences Between Touchable Components
In _React Native_, a button can be created using the built-in [`Button`](https://reactnative.dev/docs/button) component or through [`TouchableOpacity`](https://reactnative.dev/docs/touchableopacity), [`TouchableHighlight`](https://reactnative.dev/docs/touchablehighlight), and [`Pressable`](https://reactnative.dev/docs/pressable). While `Button` offers simplicity by providing basic styling,  `TouchableOpacity` and `TouchableHighlight` provide more options for customization. However, `Pressable`, introduced in React Native 0.63, is more flexible and nowadays the recommended option to handle touch-based input.

#### TouchableOpacity

- Feedback: Diminishes the opacity of the button on press.
- Use Case: Suitable for most cases where a button or an area needs to be clickable.

#### TouchableHighlight

- Feedback: Displays a "highlight" or a different background color on press.
- Use Case: Useful when a visual feedback of a color change is needed.

#### Pressable

- Feedback: Highly customizable, can define any kind of visual feedback.
- Advantages:
  - More extensive customization options for touch interactions.
  - Includes features like `onPressIn`, `onPressOut`, and `onLongPress`.
  - Handles hover and focus in addition to press states, making it more suitable for a variety of devices.
  - Allows to define a _HitRect_ area via the `hitSlop` prop to widen the area a press is registered without increasing the size of the button. Essentially, `hitSlop` specifies how far the touch area extends beyond the bounds of the visual element.
- Use Case: Recommended for new React Native projects due to its versatility and comprehensive feature set.

## Creating a Custom Button

We will now create a new customizable button component, called `AppButton`:

```jsx
import { Pressable, StyleSheet, Text } from "react-native";

const AppButton = (props) => {
  return (
    <Pressable
      style={({ pressed }) => [
        {
          backgroundColor: props.disabled
            ? "#ccc"
            : pressed
            ? "#aa0000"
            : props.color || "red",
        },
        styles.container,
        props.buttonStyles,
      ]}
      disabled={props.disabled}
      onPress={props.onPress}
      accessible
      accessibilityLabel={props.accessibilityLabel || "A Button"}
    >
      <Text style={[styles.text, props.textStyles]}>
        {props.children || "Press Me"}
      </Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 8,
    alignItems: "center",
    borderRadius: 8,
  },
  text: { color: "white" },
});

export default AppButton;
```

The `AppButton` has one required `prop`, which is the `onPress` function. It's styles can be adjusted by passing `textStyles` or `buttonStyles`. For this component, style can be passed as a function instead of an object. We use this to create a press effect by changing the background color on the press of a finger
for a short time. If the button is disabled we deactivate that effect and set it to a shade of gray to indicate this to the user visually. Last but not least, `accessible` and `accessibilityLabel` are set so that people who use [VoiceOver](https://support.apple.com/de-de/guide/iphone/iph3e2e415f/ios) or [TalkBack](https://support.google.com/accessibility/android/answer/6283677?hl=de) know what element they have selected. A screen reader will verbalize this string when the associated element is selected.

You can find an online version of the button [here](https://snack.expo.dev/riCJeQzUG_INM5EoDfj71).

## Advanced Options

- Adding Icons: Icons can be added to the button by using libraries like [react-native-vector-icons](https://www.npmjs.com/package/react-native-vector-icons).
- Animations: Animations like changing the background color can be added by using [Animated](https://reactnative.dev/docs/animated) or [LayoutAnimation](https://reactnative.dev/docs/layoutanimation).

## Conclusion

Creating a custom button in _React Native_ is a straightforward process and can significantly enhance an app's user experience. By customizing styles and adding features like icons and animations, a button that perfectly fits an app's design can be created. The `Pressable` component, with its extensive customization options, provides a versatile, future-proof and comprehensive solution for touchable interactions.