Simple Image Carousel with React

bit.ly/2CtMqAO

Here we are! Due to my master thesis at the university, one of the requirements is the implementation of an interactive mockup for the university WebTV platform. So, I decided to make it with React.

Working with the video lists filtered by category encouraged me to use nuka-carousel. Though, I used it for one of the cases to complete the task. Here you can have a look closer at the library and figure out how it works.

For another case, because of specific requirements, I needed to code the custom carousel. And now I am going to share the outcome solution.

I hope you already guessed to set up a new React application from the official tutorial.

The next step is to create a new class React component, in my case it is <Videos />. Which we are going to import and pass into render-component <App />:

// App.js
import React, { Component } from 'react';
import {Videos} from './Videos';
class App extends Component {
render() {
return (
<div className="App">
<Videos />
</div>
);
}
}
export default App;

I will skip the styling part and just present the implementation of the logical part, so let’s see what the <Videos /> component looks like:

// Videos.js
import React from 'react';
import arrowRight from './img/arrow-right.svg';
import arrowLeft from './img/arrow-left.svg';
export class Videos extends React.Component {
constructor() {
super();
  this.state = {
// holding the current index for the image that has to be rendered at each time on the screen
currentImageIndex: 0,
// array of the source links to the images, simple placeholders for now
images: [
'https://via.placeholder.com/200x150?text=first',
'https://via.placeholder.com/200x150?text=second',
'https://via.placeholder.com/200x150?text=third',
'https://via.placeholder.com/200x150?text=fourth',
'https://via.placeholder.com/200x150?text=fifth',
'https://via.placeholder.com/200x150?text=sixth',
'https://via.placeholder.com/200x150?text=seventh',
'https://via.placeholder.com/200x150?text=eighth',
'https://via.placeholder.com/200x150?text=ninth',
'https://via.placeholder.com/200x150?text=tenth'
],
// imported images of right and left arrows
arrowNext: arrowRight,
arrowPrev: arrowLeft
};
...

Above I show the data structure assigned to the state of the <Videos /> component. To change the state — list videos to the right and to the left — I have also bound two methods prevSlide() and nextSlide():

// Videos.js

...
 constructor() { 
...
this.nextSlide = this.nextSlide.bind(this);
this.prevSlide = this.prevSlide.bind(this);
}
prevSlide() {
// find the index of the last image in the array
const lastIndex = this.state.images.length - 1;
 // check if we need to start over from the last index again
const resetIndex = this.state.currentImageIndex === 0;
const index = resetIndex ? lastIndex : this.state.currentImageIndex - 1;
// assign the logical index to currentImageIndex that will use in render method
this.setState({
currentImageIndex: index
})
}
nextSlide() {
// find the index of the last image in the array
const lastIndex = this.state.images.length - 1;
 // check if we need to start over from the first index
const resetIndex = this.state.currentImageIndex === lastIndex;
const index = resetIndex ? 0 : this.state.currentImageIndex + 1;
 // assign the logical index to currentImageIndex that will use in render method
this.setState({
currentImageIndex: index
});
}

The logic isn’t complete yet. According to the project requirements the user has to see only 5 videos in the carousel and be able to cycle them over. So, moving on to the render() method I have to get a new array of 5 videos in the preview list. Inside the render():

// Videos.js
...
render() {
// get current image index
const index = this.state.currentImageIndex;
 // create a new array with 5 videos from the source images
let firstFiveVideo = this.state.images.slice(index, index + 5);
 // check the length of the new array (it’s less than 5 when index is near the end of the array)
if (firstFiveVideo.length < 5) {
 // if the firstFiveVideo's length is lower than 5 images than append missing images from the beginning of the original array 
firstFiveVideo = firstFiveVideo.concat(this.state.images.slice(0, 5 - firstFiveVideo.length))
}
return (
<div>
// render the left arrow
<img src={this.state.arrowPrev} onClick={this.prevSlide}/>
// render images
{firstFiveVideo.map((image, index) =>
<img key={index} src={image} alt=""/>
)}
// render the right arrow
<img src={this.state.arrowNext} onClick={this.nextSlide}/>
</div>
);
}

And that’s it. Below you will find the screenshot of my implementation:

As I mentioned before, I omitted the styles used for the components, because it was not the purpose of the post. So, it means you are free to apply your own styles to the project 🙂

Thank you for reading! 👏

Cheers, 
ilonacodes