Exploring React Native – Part 2

React1

Table of Contents

Previously, in “Exploring React Native (Continued Part 1), we continued to work on our simple app. The app initially consisted of an Image component, Text components, state with data, a couple of TouchableOpacity buttons and styling. The app was to keep track of the number of raccoons the user saw but we wanted to add to it. So, we add a new set of components to track the number of pigeons and added the ScrollView component for scrolling. We used the View component to build cards for each animal and learned different ways to pass styling to components.

In this article, we will learn how to create our own components. Components are the building block of React Native. They come built in but they can also be created. As stated on the React Native documentation, “When you’re building a React Native app, you’ll be making new components a lot. Anything you see on the screen is some sort of component. A component can be pretty simple – the only thing that’s required is a render function which returns some JSX to render.”

At the end of the previous article, all our code was in the “App.js” file. Our code was long and we used the same components for the each animal. We will structure our project by creating folders and files, then grouping them by type.

Let’s get started!

Creating Our Components

I will be working on a Mac using Visual Studio Code as my editor, run the app on the iOS simulator and will be working with the “FirstRNProject” project. If you are using Windows or are targeting Android, I will test the app on the Android emulator at the end of the article. This code will also work if you are using Expo and will also be tested later on.

If you are starting with a new React Native or Expo project or didn’t follow the previous article, here is the code:

App.js

import React, { Component } from 'react';
import { Button, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class App extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
)
}
}
export default App;

Our app looked like this:

As you can see the app looks great but the code is long and somewhat complicated. We are going to create our own components for the image, texts and buttons.

First begin by creating a folder inside the project, called “src”. Inside of the “src” folder, create two more folders, one called “components” and one called “screens”. I have seen others name their “src” folder, “app”, and their “screens” folder, “container”. I prefer “src” and “screens” but you can go with “app” and “container” if you would like.

Here is my project:

Now inside of the “components” folder, let’s create a files for the image, question, counter and buttons. We will named them “OurImage.js”, “Question.js”, “Counter.js” and “Button.js”. Then create a file inside of the “screens” folder called “Main.js”. Also take the “img” folder and move inside of the “src” folder.

Let’s start with the “Main.js” file. Copy everything from “App.js” and paste it into “Main.js”. Then go back to “App.js” and delete the imports from React Native, the styles, state, functions for the buttons and everything that is returned in the render function. What you are left with is:

import React, {Component} from 'react';
class App extends Component {
render() {
return (
);
}
}
export default App;

If you try running the app right now, you will get an error because nothing is being returned in the render function. What we will do is, instead of using a built in component, we will return our main screen, “Main.js”. First import the “Main.js” file located inside the “screens” folder like this:

import Main from ‘./src/screens/Main’;

It is similar to importing built in components from React Native. Now inside the render functions add the following tag:

<Main />

Your “App.js” file should look like this:

import React, {Component} from 'react';
import Main from './src/screens/Main'
class App extends Component {
render() {
return (
<Main />
);
}
}
export default App;

Try running the app again and you will notice there is still an error. The problem is that we need to change the class and export names in the “Main.js” file from “App” to “Main”.

import React, { Component } from 'react';
import { Button, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class Main extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
)
}
}
export default Main;

Reload the app and you still get an error. This is because in the “Main.js”, the Image component can not locate the raccoon image. Change the source location to:

<Image style={styles.image} resizeMode='contain' source={require('../img/raccoon.png')} />

The “..” at the beginning means that the file is located outside of the current folder and the rest of the code states that it is located in the “img” folder and is called “raccoon.png”. If the “img” folder is still outside of “src”, the location will be “../../img/raccoon.png”.

I reloaded the app and was still getting an error regarding the image location, so I closed the Metro Bundler and ran the project again. This time it worked and here is the app again:

Ok, cool. Things are working again. Let’s first work on the image component. Open up the “OurImage.js” file inside of “components” and paste this code in it:

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
})
const OurImage = () => (
);
export default OurImage;

As you can probably tell, this is a bit different. We import Image and StyleSheet from React Native, create the styles variable and export but we do not create a class. The reason for this is because this will be a stateless component. A stateless component is one that will not use lifecycle hooks, which we have not talked about yet, and has no state.

Copy the image styling from “Main.js” and paste it here. Then copy the Image component from “Main.js” and paste it here as well.

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
}
})
const OurImage = () => (
<Image style={styles.image} resizeMode='contain' source={require('../img/raccoon.png')} />
);
export default OurImage;

Go into “Main.js”, import OurImage component and replace the Image tags with OurImage.

import { Button, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import OurImage from '../components/OurImage';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
});
class Main extends Component {
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage style={styles.image} resizeMode='contain' source={require('../img/raccoon.png')} />
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage style={styles.image} resizeMode='contain' source={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>

Reload the app and now we have two raccoon images. Before continuing, let’s clean the code in “Main.js” by removing “image” from styles and the Image component import from React Native. Then inside the OurImage tags remove the style and “resizeMode” props. Rename the source prop to “imageSource”.

I realized that we have not discussed what props are. Props are properties that can be passed from a parent to child component. Certain components like View, do not need props but can take them, such as style. Other components like Image, need props or else they will not work. The built in Image component needs at least a source location for its image and possibly dimensions depending on the type of image.

{/* Raccoon */}
<OurImage imageSource={require('../img/raccoon.png')} />
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />

In the “OurImage.js” file we will pass “imageSource” to “source”.

const OurImage = ({ imageSource }) => (
<Image style={styles.image} resizeMode='contain' source={imageSource} />
);

Save both files and reload the app. We have the correct images again. Next component we will tackle is the question component. Inside of “Question.js” add the following:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question ;

This is similar to the OurImage component. First import the necessary components from React Native. Then I went ahead and copied the styling from “Main.js” file. After that, create the const Question, which will get a “question” prop, and add a Text component with the “question” prop. Going back to “Main.js”, import Question component and replace both question texts with a Question component, passing it a prop, “question”.

Here is “Main.js”:

import Question from '../components/Question';
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />

And “Question.js”:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question ;

Next component we will work on is the Counter component. Inside of “Counter.js”, copy and paste all the code from “Question.js”. Replace “Question” with “Counter”, remove the styling and props. You should be left with this:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
})
const Counter = ({ }) => (
<Text ></Text>
);
export default Counter;

This is a pretty good template, so go ahead, copy this and paste it in “Button.js”. We will work on that file next.

Go to “Main.js”, import Counter and replace the Text tags with Counter. Give these Counters a prop called “count” with the corresponding data. Then copy the styling and paste in “Counter.js”.

import Counter from '../components/Counter';
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter count={this.state.raccoons} />
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter count={this.state.pigeons} />

Our Counter component will look like this:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<Text style={styles.number} >{count}</Text>
);
export default Counter;

Things are looking great! Last component we need to work on is the Button component. First import our Button component inside of “Main.js”. Then copy one of the “PLUS” buttons and paste this in “Button.js”. Then import the necessary components from React Native. Make sure you are exporting Button and have create a “const Button”.

import React from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
})
const Button = ({ }) => (
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
);
export default Button;

Go back to “Main.js” and replace the raccoons’ buttons with Button tags. To the Button tag pass a prop for button color, “onPress” function and text. Use ‘#9FC4AD’ for the plus button and ‘#BAAAC4’ for the minus button. It will look like this:

{/* Raccoon Button */}
<View style={styles.buttonRow}>
<Button buttonColor=’#9FC4AD’
onPressed={this.addRaccoons}
text='PLUS'
/>
<Button buttonColor=’#BAAAC4’
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>

After this, go to the Button component, add button styling from “Main.js” and pass the props to the components.

Here is what you will have:

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const Button = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.plusButton, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default Button;

To the TouchableOpacity, we will pass it an array of styles. Although the way it is right now will work, because the “backgroundColor” prop in the array is called after “styles.plusButton” and will override the background color inside of “plusButton”, I would like to rename “plusButton” to “buttonStyling”. Then delete “minusButton” from styles and remove “backgroundColor” from “buttonStyling”. Rename the style prop in TouchableOpacity and you have this:

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
buttonStyling: {
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const Button = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.buttonStyling, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default Button;

After saving all the files, I reload the project and got an error. The error was because I had imported Button from React Native in “Main.js” and so it needs to be removed. It may actually be best to rename “Button.js” to “OurButton.js”, this way we can distinguish between our custom button component and the built in one. Don’t forget to change “Button” to “OurButton” in “Main.js” and “OurButton.js”.

Now that the errors have been fixed, here is what I am left with:

As you can see, the buttons for the pigeon section are not correct. This is because we removed all the button’s styling from “Main.js”. Let’s delete these buttons and use our Button component instead. If you want, simply copy the raccoon buttons and pass it the correct “onPress” functions.

<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>

Save and reload.

Excellent! Our app is running and working correctly on iOS, let’s open up the Android emulator and make sure it is working there too.

Looking good on Android. Now, let’s test it on Expo.

Expo looking great too. At this point, I suggest going to the “Main.js” and removing components and styles that are no longer used.

Main.js

import React, { Component } from 'react';
import { ScrollView, StyleSheet, View } from 'react-native';
import OurImage from '../components/OurImage';
import Question from '../components/Question';
import Counter from '../components/Counter';
import OurButton from '../components/OurButton';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class Main extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter count={this.state.raccoons} />
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addRaccoons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'http://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter count={this.state.pigeons} />
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>
</View>
</View>
</ScrollView>
)
}
}
export default Main;

OurImage.js

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
}
})
const OurImage = ({ imageSource }) => (
<Image style={styles.image} resizeMode='contain' source={imageSource} />
);
export default OurImage ;

Question.js

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question;

Counter.js

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<Text style={styles.number} >{count}</Text>
);
export default Counter;

OurButton.js

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
buttonStyling: {
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const OurButton = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.buttonStyling, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default OurButton;

Great job! We took each element of the animal card and created a reusable component. We have a component for the image, question, counter and buttons.

In the next article, we will use these custom components to add a third animal. The question will have a text input and instead of using a photo we find online, we will allow users to take a picture or use an image from the photos. Till then, make changes to this code and try to create a card component with our custom components.