How to implement a Carousel in React-Native using react-native-snap-carousel part 1
For this article I will be explaining how to add a carousel with pagination in a React-Native app using the package react-native-snap-carousel.
First things first, create a react-native app project using the below command in your terminal.
npx react-native@latest init CarouselProject
Once the project has been successfully created open it in your chosen code editor and then run the below command to install the snap carousel package.
$ npm install --save react-native-snap-carousel
There are a few props of the “Carousel” component that are frequently used when being implemented which can be found below.
Data — the array of items to loop over to show in the carousel (Array type)
renderItem — Takes a piece of data and renders it to the list. A function can be passed into this to allow for a more customized look and feel. The item and index can be passed as an argument too.
itemWidth — Width of carousel items (pixels)
sliderWidth — Width of carousel itself (pixels)
itemHeight — Height of carousel items (pixels)
sliderHeight — Height of slider (pixels)
The API we will be using will be the random user generator API which is free to use and allows us to specify the number of records we want to return, in addition to, containing information such as first and last name, furthermore, a date of birth and image.
An example of the web api call is below.
https://randomuser.me/api/?results=10
To use this API we will incorporate a package called axios which is used to make http requests, so run the below command in your code editor.
npm install axios
Once this has finished installing we will create a new file called “CarouselContainer.js” within the root of the project. This file will contain the Carousel component itself.
After creating it fill the file with the below for now.
import React from 'react';
import {View, Text} from 'react-native'
function Carousel(){
return(
<View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
<Text>
Carousel Container View
</Text>
</View>
)
}
export default CarouselContainer;
We will need to make use of the “useEffect” hook since we want the carousel to be populated with the data from the api on the load of the component.
So firstly you’ll need to import axios at the top of your component file.
import axios
To store the data that will be returned from the api we will need a state variable and function using the “useState” hook, call the state “userData” and function “setUserData” with a default value of an empty array.
const [userData, setUserData] = useState([]);
Now create a method called “getUserData” as a const variable like below.
const getUserData = () => {
}
Inside of the method we will use axios to call the api url and set the results data to the “userData” state.
const getUserData = () => {
axios.get('https://randomuser.me/api/?results=10')
.then(response=>{
if(response!==null&&response!==undefined){
console.log(response.data.results);
setUserData(response.data.results);
}
})
}
The reason I am doing “response.data.results” is because the data returned from the api is returned with an object key of “results”.
We also do a console log which we will now use to check that the data has returned successfully.
Now we need to actually make sure the function runs on the load of the component, so use the “useEffect” hook and place the function call inside. Remember to set the second argument as an empty array so it only runs on load.
useEffect(()=>{
getUserData();
},[]);
Now we need to implement the CarouselContainer component. Open the App.tsx/js file and remove all of the boilerplate so the full file looks like the below.
So run your app using the below command.
npx react-native run-ios
We will now begin to implement the Carousel component from the package. So the first thing we will need to do is import it.
import { Carousel } from 'react-native-snap-carousel';
We will set the required properties first, so set the “data” property to equal to the “userData” state, sliderWidth and itemWidth to 400.
Furthermore, there is a property called “layout” which changes the look of how the items in the carousel appear.
There are 3 values available for “layout” they are “default”, “stack” and “tinder”.
“Default” has an animation where each item appears side by side, “stack” sets the items on top of one another with a little bit of overlay to the right hand side, finally, the last option “tinder” where the carousel mimics the famous tinder swipe so the items are on top of one another and you can swipe right or left.
The first thing we will do is remove the <Text> component that we created earlier just to show some template text.
We will also add “flexDirection:row” to the container view to change the main axis that the child elements appear in, so now our container view looks like the below.
<View style={{ flex: 1, flexDirection:'row', justifyContent: 'center', alignItems: 'center' }}>
</View>
We will now implement the Carousel component and set the necessary props, so as described earlier we will set the “data” prop equal to the “userData” state, set “sliderWidth” and “itemWidth” to 380 and layout to “default”. So now our Carousel component looks like the below.
<Carousel
data={userData}
sliderWidth={380}
itemWidth={380}
layout={'default'}
/>
However, we need to determine how to diplay the items in the carousel and for that we will need to implement the “renderItem” property of the Carousel component, this property takes in a function and passes the item (and its data) and index to the function and will return a View to show for each item.
So create a function in the same file called “renderUserItem” and destructure the 2 parameters as “item, index” like the below.
const renderUserItem = ({item,index}) => {
return(
)
}
So inside this function we are first going to have a View with a few style values including height, margin and background colour.
<View
style={{backgroundColor:'lightblue', borderRadius:5, height:380,
marginLeft:25, marginRight:25
}}>
</View>
Now that we have that we will have a text component which will show the users first name, if you look at examples of response data from the api you can see how the data is structured.
<Text style={{fontSize:20, textAlign:'center', justifyContent:'center'}}>{item.name.first}</Text>
So we access the firstname property value traversing the response item data of item and in the response example found on the site above we can see the key of the name object is “name” and inside this object are 3 properties “title”, “first” and “last”.
Now you can run your project and you should something similar to below and if you drag from left to or vice versa then you should be able to see the additional items from the list.
We will now go ahead and add more properties to show on the item to make it look more legitimate and organise the code a bit better.
So firstly we will add a View component inside of the initial View in the function and we will give this a marginTop of 20 (this is to apply for all properties within the function)
<View style={{marginTop:20}}>
</View>
Inside of this we will create another View component that will contain the image of the user. This View will have a property of alignItems: ‘center’ to center the image within the view.
<View style={{ alignItems: 'center' }}>
</View>
Inside of this View we will have an Image component and the image that is returned from the api is from a URL so we will have to set the source property of the Image component but set it to “uri” so it looks for a url to pull the image from. The image is found within the picture object of the response, we will also need to set a height and width property of 200.
<Image source={{ uri: item.picture.large }} width={200} height={200} />
Outside of the Image components container we will create another View with a marginTop of 10 and inside of this we will have the first and last name of the user.
<Text style={{ fontSize: 20, textAlign: 'center', justifyContent: 'center' }}>{item.name.first} {item.name.last}</Text>
So the current content inside of our second outer view is.
<View style={{ alignItems: 'center' }}>
<Image source={{ uri: item.picture.large }} width={200} height={200} />
</View>
<View style={{ marginTop:10 }}>
<Text style={{ fontSize: 20, textAlign: 'center', justifyContent: 'center' }}>{item.name.first} {item.name.last}</Text>
</View>
We will have another View component with marginTop of 10 and a Text component accessing the email property.
<View style={{marginTop:10 }}>
<Text style={{ fontSize: 12, textAlign: 'center', justifyContent: 'center'}}>{item.email}</Text>
</View>
Finally, we will also inclue the city, state and country properties which are found within the “location” object.
<View style={{ marginTop: 10 }}>
<Text style={{ fontSize: 20, textAlign: 'center', justifyContent: 'center' }}>{item.location.city} , {item.location.state}, {item.location.country}</Text>
</View>
So our full code for the function looks like the below.
const renderUserItem = ({ item, index }) => {
return (
<View
style={{
backgroundColor: 'lightblue', borderRadius: 5, height: 380,
marginLeft: 25, marginRight: 25,
}}>
<View style={{ marginTop: 20 }}>
<View style={{ alignItems: 'center' }}>
<Image source={{ uri: item.picture.large }} width={200} height={200} />
</View>
<View style={{ marginTop: 10 }}>
<Text style={{ fontSize: 20, textAlign: 'center', justifyContent: 'center' }}>{item.name.first} {item.name.last}</Text>
</View>
<View style={{ marginTop: 10 }}>
<Text style={{ fontSize: 12, textAlign: 'center', justifyContent: 'center' }}>{item.email}</Text>
</View>
<View style={{ marginTop: 10 }}>
<Text style={{ fontSize: 20, textAlign: 'center', justifyContent: 'center' }}>{item.location.city} , {item.location.state}, {item.location.country}</Text>
</View>
</View>
</View>
)
}
If you now run the application you should something like the below.
It is not the best looking carousel item and the styling could have been organised better instead of being inline but for a first Carousel it isn’t too bad, you can edit it to your hearts content and make it incredibly fancy.
In the next tutorial I will go over the Pagination component of the react-native-snap-carousel which works very well with the Carousel and gives a visual indication as to what item the user is currently on as well as how many there are left to scroll through.
Thank you for reading and don’t forget to follow me/clap the article!