React JS Create Shop Page with Skeleton Loading

Most of today’s modern interactive apps load data from the background and the data to be loaded will take some time as the server needs to send the data.
Till then the app must wait till the data is displayed. And in-between of these processes it can developers would display a circular loading which let
users know that the data is loading and they would wait.

These designs bother most of the frontend and UI/UX developers and then they changed it by using a dummy screen which acts as a placeholder for the layout of the actual
element. This looks more intuitive and effective as users may know that the data will load soon.

In this Product, I’ll show how you can easily create a skeleton in React JS. I’ll be taking an example of a shop page where I’ll load products after the page is loaded.

For skeleton loaders, we’ll use react-content-loader package.

Watch Video

Installation

Start by installing package react-content-loader which creates SVG Placeholders.

npm i react-content-loader --save

Preparing Loaders

In src\components\loaders\product-loader.js

import React from 'react'
import ContentLoader from "react-content-loader"

export default function ProductLoader( props ) {
    const count = ( props.count )? parseInt(props.count) : 1
    
    return (
        <>
            { 
                [...Array(count)].map( ( item, index ) => {
                    return (
                        <ContentLoader key={index} viewBox="0 0 500 420" height={400} width={500} {...props}>
                            <rect x="16" y="17" rx="0" ry="0" width="360" height="200" />
                            <circle cx="35" cy="248" r="20" />
                            <rect x="69" y="229" rx="2" ry="2" width="275" height="15" />
                            <rect x="69" y="253" rx="2" ry="2" width="140" height="15" />
                        </ContentLoader>
                    )
                } ) 
            } 
        </>       
    )
}

The ProductLoader the component will load the skeleton and there is a count variable that will load multiple of such placeholders.

Recommended

The loaders templates are available in skeletonreact. Just copy the code and add it to the component to reduce development time.

Design Product Card Component

In src\components\product-card.js

import React from 'react'
import styles from 'components/product-card.module.css'

export default function ProductCard( { product, ...props } ) {
    return (
        <div className={styles['product-card']} >
           <div className={styles['product-card-header']} >
                <div className={styles['product-card-image-wrapper']} >
                    <img src={product.image} className={styles['product-card-image']} alt="" />
                </div>
                <div>
                    <p className={styles['product-card-title']} >{product.title}</p>
                </div>
            </div> 
            <div className={styles['product-card-body']} >
                <img src={product.image} className={styles['product-card-body-image']} alt="" />
            </div> 
        </div>
    )
}

The component ProductCard return a single card element. We have to loop over each one of them to display multiple of them.

Styling Product Card Component

In src\components\product-card.module.css

.product-card{
    border: 1px solid #ccc;
    margin: 5px 0;
}

.product-card-image-wrapper{
    display: flex;
    align-items: center;
}

.product-card-image{
    width: 50px;
    height: 50px;
    border-radius: 50%;
    border: 3px solid #eee;
}

.product-card-body-image{
    width: 100%;
    height: 150px;
    object-fit: contain;
}

.product-card-header{
    display : flex;
    gap:10px;
    border-bottom: 1px solid #ccc;
    padding: 3px 5px;
}

.product-card-body{
    padding: 10px 5px;
}

.product-card-body p{
    margin: 0;
}
    

Loading Skeleton in Shop Page

In src\App.js

import React, { useEffect, useState } from 'react'
import styles from './App.module.css'
import ProductLoader from 'components/loaders/product-loader'
import ProductCard from 'components/product-card'

function App() {

    const [products, setProducts] = useState([])

    useEffect( ()=>{
        init()
    }, [] )

    const init = async()=>{
        let res = await fetch( "https://fakestoreapi.com/products" )
        res = await res.json()

        setProducts([...res])
    }

    return (
        <>
            <div className={styles['container']} >
                <div>
                    <h4 style={{textAlign:'center'}} >Shop</h4>
                </div>
                <div className={styles['product-items-container']} >
                {
                    ( products.length )
                    ? products.map( ( item, index ) => {
                        return ( <ProductCard key={index} product={item} /> )
                        } )
                    : ( <ProductLoader count={5} /> )
                }
                </div>
            </div>      
        </>
    );

}


export default App;

We have declared [products, setProducts] as states and while rendering if they products are empty then we’ll display ProductLoader components.
The function init() will be invoked after the page is loaded which fetches the products and updates products state.

In src\App.module.css

.container{
    width: 80%;
    margin: auto;
}

.product-items-container{
    width: 400px;
    margin: auto;
}

Here we are doing basic styling for alignment purpose.

For data we have used fakestoreapi

Next include App in index.js
In src\index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>,
    document.getElementById('root')
);

Output

Final Ouput Of React Js Skeleton Loading for displaying products in shop page
Final Output Of React Js Skeleton Loading for displaying products on shop page

Sandbox

Find code to Github Repository