Create Radio Button Group in React-Native
Published: 2020-12-15 19:58:09

Hello folks,

Today we're going to create a radio button example from react-native without using any third-party library.

First, create a new react native project using the following command. Please select the default template, if you are prompted to select a template.

```
create-react-native-app radio-button-demo
``` 
Then navigate to the project directory and start the app.


```bash
npm run ios
``` 

Your newly created app will look similar to the following.


![Screenshot 2020-12-16 at 00.15.39.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1608057991407/Kae3Q_6DU.png)

Now Let's start working on the app to add radio buttons.

First, create two files as `RadioButton.js` and `RadioButtonContainer.js` in the root of the project directory. Your project structure will be as follows.

![Screenshot 2020-12-16 at 00.18.58.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1608058144106/Je_ZMKf9B.png)

Our radio buttons will look like this.

![Screenshot 2020-12-16 at 00.21.25.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1608058292617/wxcYrWzez.png)

Now let's create the react component for a single radio button.


```js
export default function RadioButton() {

  return (
    <TouchableOpacity style={styles.mainContainer}>
      <View style={[styles.radioButtonIcon]}>
        <View style={[styles.radioButtonIconInnerIcon]} />
      </View>
      <View style={[styles.radioButtonTextContainer]}>
        <Text style={styles.radioButtonText}>Option A</Text>
      </View>
    </TouchableOpacity>
  );
}
``` 

Also, add the following styles to make it looks better.

```js
const styles = StyleSheet.create({
  mainContainer: {
    height: 50,
    marginTop: 5,
    marginBottom: 5,
    marginLeft: 10,
    marginRight: 10,
    justifyContent: "center",
    paddingLeft: 10,
    paddingRight: 10,
    borderWidth: 0.5,
    borderColor: "red",
    flexDirection: "row",
    alignItems: "center",
  },
  radioButtonIcon: {
    backgroundColor: "white",
    borderWidth: 3,
    borderColor: "red",
    height: 30,
    width: 30,
    borderRadius: 30 / 2,
    marginRight: 10,
    alignItems: "center",
    justifyContent: "center",
  },
  radioButtonIconInnerIcon: {
    height: 25,
    width: 25,
    backgroundColor: "red",
    borderRadius: 25 / 2,
    borderWidth: 3,
    borderColor: "white",
  },
  radioButtonTextContainer: {
    flex: 5,
    height: 50,
    justifyContent: "center",
    paddingLeft: 10,
  },
  radioButtonText: {
    fontSize: 18,
  },
});
```

Now we have a better UI for our radio button. But we need to have multiple radio buttons.

Now let's create multiple radio buttons with some dynamic data which should look exactly as follows.


![Screenshot 2020-12-16 at 00.31.53.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1608058916908/JMm1UFSTo.png)

For this, we need to change the code in our `RadioButtonContainer.js`, `App.js`, `RadioButton.js` files. Let's make those changes.

Inside your `RadioButtonContainer.js` file, paste the following code. I will go for a detailed explanation later on.

```js
import React, { useState, useEffect } from "react";
import { View, Text } from "react-native";
import RadioButton from "./RadioButton";

export default function RadioButtonContainer({ values, onPress }) {
  const [currentSelectedItem, setCurrentSelectedItem] = useState(0);

  const _onPress = (idx) => {
    onPress(idx);
    setCurrentSelectedItem(idx);
  };

  const _renderRadioButtons = () => {
    return (values || []).map((listItem, idx) => {
      let isChecked = currentSelectedItem === idx ? true : false;
      return (
        <RadioButton
          key={idx}
          onRadioButtonPress={() => _onPress(idx)}
          isChecked={isChecked}
          text={listItem.text}
        />
      );
    });
  };
  return <View>{_renderRadioButtons()}</View>;
}
```

Now you will wonder what this `{values, onPress }` refers to. These will be the props passed from the parent component to this `RadiobuttonContainer` component. `values` will contain a data list for radio buttons and `onPress` will have a function to be called on click of each the radio button.


```js
const [currentSelectedItem, setCurrentSelectedItem] = useState(0);
```

by using the above line we make sure that 1st value in the data list is checked by default.

Then we use the JS array `map` function to render multiple components of `RadioButton`.


```js
  const _renderRadioButtons = () => {
    return (values || []).map((listItem, idx) => {
      let isChecked = currentSelectedItem === idx ? true : false;
      return (
        <RadioButton
          key={idx}
          onRadioButtonPress={() => _onPress(idx)}
          isChecked={isChecked}
          text={listItem.text}
        />
      );
    });
  };
```

Now you can see there are multiple props passed into the `RadioButton` component. Let's have a look at it.

- `onRadioButtonPress` will be called on the press of the relevant radio button and gives the index in the data list.
- `isChecked` will determine whether each radio button is checked or not.
- `text` will be responsible for the text shown in the body of the radio button.

```js
const _onPress = (idx) => {
    onPress(idx);
    setCurrentSelectedItem(idx);
  };
```

The above function is responsible for changing the UI in the selected radio button.`onPress` is the function passed from the parent component. `setCurrentSelectedItem` will update what is the currently checked radio button.

Now we need to pass props into our `RadioButtonContainer`. Let's find out how it is done.

Remove all the content in the `App.js` file and paste the following code.

```js
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View, SafeAreaView } from "react-native";
import RadioButtonContainer from "./RadioButtonContainer";

export default function App() {
  const data = [
    {
      text: "Option A",
    },
    {
      text: "Option B",
    },
    {
      text: "Option C",
    },
    {
      text: "Option E",
    },
    {
      text: "Option F",
    },
    {
      text: "Option G",
    },
  ];

  const onRadioButtonPress = (itemIdx) => {
    console.log("Clicked", itemIdx);
  };

  return (
    <SafeAreaView>
      <View style={styles.textContainer}>
        <Text style={styles.text}>Radio Button Demo</Text>
      </View>

      <RadioButtonContainer values={data} onPress={onRadioButtonPress} />
      <StatusBar style="auto" />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  textContainer: {
    justifyContent: "center",
    alignItems: "center",
    marginBottom: 10,
  },
  text: {
    fontSize: 20,
    fontWeight: "bold",
  },
});
```



- `data` is an object array, which is used to pass options for radio buttons. but you can use any array here which includes the `text` property in each object.
- `onRadioButtonPress` will be called on each click of the radio button with the selected index as a parameter.

Next, We need to make some changes in our `RadioButton.js` file in order to align with the latest changes.
First of all, we need to catch all the props from the parent component.

```js
export default function RadioButton()
```

change the above line to 

```js
export default function RadioButton({ isChecked, text, onRadioButtonPress })
```

in order to catch props from the parent component. Also, change the `return` code in the `RadioButton` from 

```js
  return (
    <TouchableOpacity style={styles.mainContainer}>
      <View style={[styles.radioButtonIcon]}>
        <View style={[styles.radioButtonIconInnerIcon]} />
      </View>
      <View style={[styles.radioButtonTextContainer]}>
        <Text style={styles.radioButtonText}>Option A</Text>
      </View>
    </TouchableOpacity>
  );

```
to this

```js
  const _renderCheckedView = () => {
    return isChecked ? (
      <View style={[styles.radioButtonIconInnerIcon]} />
    ) : null;
  };

  return (
    <TouchableOpacity style={styles.mainContainer} onPress={onRadioButtonPress}>
      <View style={[styles.radioButtonIcon]}>{_renderCheckedView()}</View>
      <View style={[styles.radioButtonTextContainer]}>
        <Text style={styles.radioButtonText}>{text}</Text>
      </View>
    </TouchableOpacity>
  );
```

After doing all those changes, Your `RadioButton.js` file looks like this.

```js
import React, { useState } from "react";
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";

export default function RadioButton({ isChecked, text, onRadioButtonPress }) {
  const _renderCheckedView = () => {
    return isChecked ? (
      <View style={[styles.radioButtonIconInnerIcon]} />
    ) : null;
  };

  return (
    <TouchableOpacity style={styles.mainContainer} onPress={onRadioButtonPress}>
      <View style={[styles.radioButtonIcon]}>{_renderCheckedView()}</View>
      <View style={[styles.radioButtonTextContainer]}>
        <Text style={styles.radioButtonText}>{text}</Text>
      </View>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  mainContainer: {
    height: 50,
    marginTop: 5,
    marginBottom: 5,
    marginLeft: 10,
    marginRight: 10,
    justifyContent: "center",
    paddingLeft: 10,
    paddingRight: 10,
    borderWidth: 0.5,
    borderColor: "red",
    flexDirection: "row",
    alignItems: "center",
  },
  radioButtonIcon: {
    backgroundColor: "white",
    borderWidth: 3,
    borderColor: "red",
    height: 30,
    width: 30,
    borderRadius: 30 / 2,
    marginRight: 10,
    alignItems: "center",
    justifyContent: "center",
  },
  radioButtonIconInnerIcon: {
    height: 25,
    width: 25,
    backgroundColor: "red",
    borderRadius: 25 / 2,
    borderWidth: 3,
    borderColor: "white",
  },
  radioButtonTextContainer: {
    flex: 5,
    height: 50,
    justifyContent: "center",
    paddingLeft: 10,
  },
  radioButtonText: {
    fontSize: 18,
  },
});
```

After following all the above steps, you should have a nice looking radio button group.


![Simulator Screen Shot - iPhone 11 - 2020-12-16 at 01.03.52.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1608060943788/TAh9PKsjT.png)