DEV Community

loading...
Cover image for Make your own customized and reusable React Native button component

Make your own customized and reusable React Native button component

Abdul Basit
MERN Stack Developer at Orange Fox Labs
・4 min read

Recently, I am working on a mobile app where I need couple of buttons on different screens, like one for submit, login, etc.

I want to make a reusable button once for all that change its style, shape, and size by accepting props.

When I researched I found couple of things.
There are two kinds of buttons, that are mostly preferred, outlined and filled. Then we can add further properties to it as per our design like size and shape.

How it will help

It will make our code look clean, precise and easily scalable.

Lets Start

I am assuming you know how to create a react native app and other basic things.

Breakdown the task into pieces

We know we need to pass 5 props.

  1. button text
  2. onPress
  3. type (filled or outlined)
  4. border (true or false)
  5. size (large or small)

Our button text (like Submit, Delete, etc) will always be different, so we will get the text via props, and each button will have different functionality for that we are passing onPress props too.

Our button will look like this

By default its type is filled, large in size and without border.

Buttons.js

import React from 'react'
import { Text, View, TouchableOpacity, Dimensions, StyleSheet } from 'react-native'


const width = Dimensions.get('window').width


const Button = ({ text, onPress }) => {
  return (
    <TouchableOpacity onPress={onPress}>
      <View style={styles.btnContainerStyle}>
        <Text style={styles.btnTextStyle}> {text} </Text>
      </View>
    </TouchableOpacity>
  )
}

const styles = StyleSheet.create({
  btnContainerStyle: {
    backgroundColor: '#3F51B5',
    paddingVertical: 8,
    width: width / 1.3,
    borderRadius: 5
  },
  btnTextStyle: {
    color: '#ffffff',
    fontSize: 16,
    textTransform: 'uppercase',
    textAlign: 'center',
    fontFamily: 'Quicksand-Medium'
  }
})

export default Button
Enter fullscreen mode Exit fullscreen mode

App.js

import React from 'react';
import { View } from 'react-native';
import Button from './src/components/Button';

const App = () => {

  const onPress = () => {
    alert('clicked')
  }

  return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Button
          text='Submit'
          onPress={onPress}
        />
      </View>
  );
};

export default App
Enter fullscreen mode Exit fullscreen mode

Size
Lets play with size first. Right now our button just accepting two props onPress and text. We want its size to become small if we pass size='small' props to it.

It's pretty easy, for large size, we are dividing the total width of the device by 1.3, similarly, for small size, we will divide the width by 1.2

const large = width / 1.3
const small = width / 2
const btnSize = size === 'large' ? large : small
Enter fullscreen mode Exit fullscreen mode

In StyleSheet, width will be equal to btnSize.

First, it will check if the size props (that we are passing from App.js) is small or large then it will act accordingly.

Type
Lets come to the type of button. Either we want filled or outlined.

We have noticed, if we change three properties, our button type will become outlined from filled. Those properties are Background color, text color and border.

By default, our button type is filled. So will say

const btnBgColor = type === 'filled' ? '#3f51b5' : 'transparent'
const btnTextColor = type === 'filled' ? '#ffffff' : '#6371c2' 
const border = type === 'outlined' && { borderColor: '#e7e7e7', borderWidth: 2 }
Enter fullscreen mode Exit fullscreen mode

Now background color will be btnBgColor and text color will be btnTextColor, and if type prop is outlined we are adding two more properties in button style.

Border
We are only left with border radius, it would be tackled similar way.

const btnBorderRadius = bordered ? 30 : 5
Enter fullscreen mode Exit fullscreen mode

Optional
Sometimes we want to make button disable too until the form is filled, for that, we can pass the disabled props and Icon can also be added.
We can make it more interactive by giving an effect on onPress.

In a similar way, we can make TextInput component reusable too.

If this article helps you, let me know in the comment section. I will write more on react native.

This is how it looks like at the end

Complete code

  • Button.js
import React from 'react'
import { Text, View, TouchableOpacity, Dimensions } from 'react-native'


const width = Dimensions.get('window').width


const Button = ({ text, onPress, type = 'filled', bordered = false, size = 'large' }) => {
  const large = width / 1.3
  const small = width / 2
  const btnSize = size === 'large' ? large : small
  const btnBgColor = type === 'filled' ? '#3f51b5' : 'transparent'
  const btnTextColor = type === 'filled' ? '#ffffff' : '#6371c2'
  const btnBorderRadius = bordered ? 30 : 5

  const containerCommonStyle = {
    backgroundColor: btnBgColor,
    paddingVertical: 8,
    width: btnSize,
    borderRadius: btnBorderRadius
  }

  const textCommonStyle = {
    color: btnTextColor,
    fontSize: 16,
    textTransform: 'uppercase',
    textAlign: 'center',
    fontFamily: 'Quicksand-Medium'
  }

  const border = type === 'outlined' && { borderColor: '#e7e7e7', borderWidth: 2 }

  return (
    <TouchableOpacity onPress={onPress} activeOpacity={0.7}>
      <View style={[containerCommonStyle, border]}>
        <Text style={[textCommonStyle]}> {text} </Text>
      </View>
    </TouchableOpacity>
  )
}

export default Button
Enter fullscreen mode Exit fullscreen mode
  • App.js
import React from 'react';
import { View } from 'react-native';
import Button from './src/components/Button';
import Spacer from './src/components/Spacer';
import Center from './src/components/Center';


const App = () => {

  const onPress = () => {
    alert('clicked')
  }

  return (
    <Center>
      <Button
        text='Submit'
        type='outlined'
        bordered
        size='small'
        onPress={onPress}
      />
      <Spacer />
      <Button
        text='Submit'
        type='outlined'
        bordered
        onPress={onPress}
      />
      <Spacer />
      <Button
        text='Submit'
        type='outlined'
        onPress={onPress}
      />
      <Spacer />
      <Button
        text='Submit'
        size='small'
        onPress={onPress}
      />
      <Spacer />
      <Button
        text='Submit'
        bordered
        onPress={onPress}
      />
      <Spacer />
      <Button
        text='Submit'
        onPress={onPress}
      />
    </Center>
  );
};

export default App
Enter fullscreen mode Exit fullscreen mode

I have added Center component to center horizontally and vertically the items and Spacer for having some vertical space between two items.

Here you can find the github repo

Discussion (2)

Collapse
platoonic profile image
Khalid Magdy Khalil • Edited

A better approach to pass the button text is to use "props.children" and use it this way:


<Button>Button Text</Button>
Collapse
dpospos profile image
DPOSPOS

thank you