In this tutorial, I'll cover how to build a simple image gallery lightbox in React js. In this project without using any additional external packages.

React Simple Image Slider

Simple Carousel in React js

Setup

Create your react project. In your terminal/command line enter:

npx create-react-app image-lightbox
cd image-lightbox
npm start 

Next, Project structure your folder as follows.

src
├── App.css
├── App.js
├── App.test.js
├── components
|   ├── Carousel  
|    └── carousel.css
|     └── Carousel.js
├── Lightbox.js
├── index.css
├── index.js
├── reportWebVitals.js
└── setupTests.js 

Next, open up the App.js file located in the src folder. You should see this:

App.js
import React, {useState, useEffect} from 'react'; import axios from 'axios'; import Lightbox from './Lightbox'; import './App.css'; function App() { const [isLoading, setLoading] = useState(false) const [isError, setError] = useState(false) const [isdata, setData] = useState({}); useEffect(() => { fetchData(); }, []); const fetchData = async () => { try { setError(false); axios.get("http://localhost:8080/ViewImage") .then(res => { // then print response status console.warn(res.data.listall); if(res.data.success === true){ setData(res.data.listall); setLoading(true); } }) } catch (error) { setError(true); } }; return ( <div className="App"> <div className="container"> <div className="row"> {isError && <div>Something went wrong ...</div>} {isLoading === false ? ( <div>Loading ...</div> ) : ( <> <Lightbox viewImage={isdata} /> </> )} <pre>{JSON.stringify(isdata, null, 2)} </pre> </div> </div> </div> ); } export default App;
Lightbox.js
import React,{useState} from 'react'; import Carousel from "./components/Carousel/Carousel" const Lightbox = (props) => { const images = props.viewImage.map((itemall) => (itemall.image)); const [imageToShow, setImageToShow] = useState(""); const [lightboxDisplay, setLightBoxDisplay] = useState(false); //looping through our images array to create img elements const imageCards = props.viewImage.map((listall) => ( <img onClick={() => showImage(listall.image)} src={listall.image} /> )); //function to show a specific image in the lightbox, amd make lightbox visible const showImage = (image) => { setImageToShow(image); setLightBoxDisplay(true); }; //hide lightbox const hideLightBox = () => { setLightBoxDisplay(false); }; //show next image in lightbox const showNext = (e) => { e.stopPropagation(); let currentIndex = images.indexOf(imageToShow); if (currentIndex >= images.length - 1) { let loopsimg = props.viewImage.length - 1; let nextImage = images[currentIndex - loopsimg ]; setImageToShow(nextImage); //setLightBoxDisplay(false); } else { let nextImage = images[currentIndex + 1]; setImageToShow(nextImage); } }; //show previous image in lightbox const showPrev = (e) => { e.stopPropagation(); let currentIndex = images.indexOf(imageToShow); if (currentIndex <= 0) { let loopsimg = props.viewImage.length - 1; let nextImage = images[currentIndex + loopsimg ]; setImageToShow(nextImage); // setLightBoxDisplay(false); } else { let nextImage = images[currentIndex - 1]; setImageToShow(nextImage); } }; return ( <> {props.viewImage.map((item, index) => ( <div className="col-md-3 " key={item.id} > <img className="image-card" onClick={() => showImage(item.image)} src={item.image} /> </div> ))} {lightboxDisplay ? <> <div id="lightbox" > <div className="container"> <div className="row"> <div className="col-md-12" > <div className="lightbox__view" > <p className="lightbox__close" onClick={hideLightBox}> X Close </p> <button onClick={showPrev} className="arrow__left">⭠</button> <img id="lightbox-img" src={imageToShow}></img> <button onClick={showNext} className="arrow__right">⭢</button> </div> <div className="clearfix"></div> <Carousel show={6} > {props.viewImage.map((item, index) => ( <div key={item.id}> <div style={{padding: 17}} > <img className="image-card-carousel" onClick={() => showImage(item.image)} src={item.image} /> </div> </div> ))} </Carousel> </div> </div> </div> </div> </> : null } </> ) } export default Lightbox
Carousel.js
import React, { useEffect, useState } from 'react' import './carousel.css' const Carousel = (props) => { const {children, show} = props const [currentIndex, setCurrentIndex] = useState(0) const [length, setLength] = useState(children.length) const [touchPosition, setTouchPosition] = useState(null) // Set the length to match current children from props useEffect(() => { setLength(children.length) }, [children]) const next = () => { if (currentIndex < (length - show)) { setCurrentIndex(prevState => prevState + 1) } } const prev = () => { if (currentIndex > 0) { setCurrentIndex(prevState => prevState - 1) } } const handleTouchStart = (e) => { const touchDown = e.touches[0].clientX setTouchPosition(touchDown) } const handleTouchMove = (e) => { const touchDown = touchPosition if(touchDown === null) { return } const currentTouch = e.touches[0].clientX const diff = touchDown - currentTouch if (diff > 5) { next() } if (diff < -5) { prev() } setTouchPosition(null) } return ( <div className="carousel-container"> <div className="carousel-wrapper"> {/* You can alwas change the content of the button to other things */} { currentIndex > 0 && <button onClick={prev} className="left-arrow"> ⭠ </button> } <div className="carousel-content-wrapper" onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} > <div className={`carousel-content show-${show}`} style={{ transform: `translateX(-${currentIndex * (100 / show)}%)` }} > {children} </div> </div> {/* You can alwas change the content of the button to other things */} { currentIndex < (length - show) && <button onClick={next} className="right-arrow"> ⭢ </button> } </div> </div> ) } export default Carousel
carousel.css
.carousel-container { width: 100%; display: flex; flex-direction: column; } .carousel-wrapper { display: flex; width: 100%; position: relative; } .carousel-content-wrapper { overflow: hidden; width: 100%; height: 100%; } .carousel-content { display: flex; transition: all 250ms linear; -ms-overflow-style: none; /* hide scrollbar in IE and Edge */ scrollbar-width: none; /* hide scrollbar in Firefox */ } /* hide scrollbar in webkit browser */ .carousel-content::-webkit-scrollbar, .carousel-content::-webkit-scrollbar { display: none; } .carousel-content > * { width: 100%; flex-shrink: 0; flex-grow: 1; } .carousel-content.show-2 > * { width: 50%; } .carousel-content.show-3 > * { width: calc(100% / 3); } .carousel-content.show-4 > * { width: calc(100% / 4); } .carousel-content.show-5 > * { width: calc(100% / 5); } .carousel-content.show-6 > * { width: calc(100% / 6); } .left-arrow, .right-arrow { position: absolute; z-index: 1; top: 50%; transform: translateY(-50%); width: 48px; height: 48px; border-radius: 24px; background-color: white; border: 1px solid #ddd; } .left-arrow { left: 24px; } .right-arrow { right: 24px; } .image-card-carousel { width: 100%; height: 87px; object-fit: cover; object-position: center top; cursor: pointer; } @media (hover: none) and (pointer: coarse) { .left-arrow, .right-arrow { display: none; } }

React slider fetch title and images into the MySQL database

In the following example, we will start how to React slider fetch title and images into the MySQL database using Node js.

  • Database Name – codeat21
  • Table Name – posts
codeat21
CREATE TABLE `posts` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `image` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Next, Node js project structure your folder as follows.

├── config
|  ├── database.js	  
├── database.js
├── index.js
├── package.js
└── package-lock.js 
database.js
const util = require('util'); const mysql = require('mysql2'); const pool = mysql.createPool({ connectionLimit: 10, host : 'localhost', user : 'root', password : '', database : 'codeat21' }); // Ping database to check for common exception errors. pool.getConnection((err, connection) => { if (err) { if (err.code === 'PROTOCOL_CONNECTION_LOST') { console.error('Database connection was closed.'); } if (err.code === 'ER_CON_COUNT_ERROR') { console.error('Database has too many connections.'); } if (err.code === 'ECONNREFUSED') { console.error('Database connection was refused.'); } } if (connection) connection.release(); return; }); // Promisify for Node.js async/await. pool.query = util.promisify(pool.query); module.exports = pool;
index.js
const express = require('express'); const app = express(); const path = require('path'); const cors = require('cors'); const port = process.env.PORT || 8080; // Databse Connection const db_connection = require('./config/database').promise(); app.use(cors()); app.get('/ViewImage', async (req, res) => { try { const [rows] = await db_connection.execute("SELECT * FROM posts "); return res.json({ success: true, listall:rows, }); } catch (err) {console.log(err)} }); app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))