While working on a React project for a U.S.-based client, I needed to display a loading spinner whenever data was being fetched from an API.
I quickly realized that even though React makes UI rendering simple, handling loading states with a smooth spinner requires a bit of setup. So, I decided to create a reusable React Loading Spinner Component that I could use across multiple apps.
In this tutorial, I’ll show you two simple methods to create a loading spinner in React, one using pure CSS and the other using the react-spinners library. Both are easy to implement and will give your application a professional touch.
What is a Loading Spinner in React?
A loading spinner is a visual indicator that tells users something is happening in the background, like fetching data from an API or processing a request.
It’s a small but powerful way to improve user experience. Without it, users might think your app is frozen or unresponsive.
Method 1 – Create a Custom Loading Spinner Using CSS
This is my favorite method when I want full control over the spinner’s design and don’t want to rely on external libraries.
Here’s how you can build a simple yet elegant spinner from scratch.
Step 1: Create a New React App
If you don’t already have a React app, create one using the command below:
npx create-react-app react-spinner-demo
cd react-spinner-demo
npm startThis sets up a new React project and runs it on http://localhost:3000.
Step 2: Create the Spinner Component
Inside the src folder, create a new file called Spinner.js and add the following code:
// Spinner.js
import React from "react";
import "./Spinner.css";
const Spinner = () => {
return (
<div className="spinner-container">
<div className="spinner"></div>
<p>Loading data, please wait...</p>
</div>
);
};
export default Spinner;Here, I created a simple functional component that displays a circular spinner and a short loading message.
Step 3: Add Spinner Styles
Now, create a Spinner.css file in the same folder and add the following code:
/* Spinner.css */
.spinner-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
.spinner {
border: 6px solid #f3f3f3;
border-top: 6px solid #0078d7;
border-radius: 50%;
width: 60px;
height: 60px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
p {
margin-top: 10px;
color: #333;
font-size: 16px;
font-family: Arial, sans-serif;
}This CSS creates a circular spinner that continuously rotates. The blue color (#0078d7) matches Microsoft’s theme, giving it a clean, professional look.
Step 4: Use the Spinner in Your App
Open App.js and replace the existing code with:
// App.js
import React, { useState, useEffect } from "react";
import Spinner from "./Spinner";
function App() {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState([]);
useEffect(() => {
// Simulate API call
setTimeout(() => {
setUsers([
{ id: 1, name: "John Doe", city: "New York" },
{ id: 2, name: "Emily Carter", city: "Los Angeles" },
{ id: 3, name: "Michael Brown", city: "Chicago" },
]);
setLoading(false);
}, 2000);
}, []);
if (loading) {
return <Spinner />;
}
return (
<div style={{ padding: "20px" }}>
<h2>Registered Users</h2>
<ul>
{users.map((user) => (
<li key={user.id}>
{user.name} ({user.city})
</li>
))}
</ul>
</div>
);
}
export default App;Here, I simulated an API call using setTimeout. While the data loads, the spinner appears. Once the data is ready, it displays the user list.
Result
When you run the app, you’ll see a smooth circular spinner with a “Loading data…” message for 2 seconds before the user list appears.
You can see the output in the screenshot below.

This is a clean, reusable solution that works great for most React projects.
Method 2 – Use the react-spinners Library
If you prefer ready-made components, the react-spinners library is a great choice. It provides a collection of prebuilt, customizable spinners.
Step 1: Install the Library
Run the following command in your project folder:
npm install react-spinnersStep 2: Import and Use the Spinner
Open your App.js file and modify it as follows:
// App.js
import React, { useState, useEffect } from "react";
import { ClipLoader } from "react-spinners";
function App() {
const [loading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
// Simulate API call
setTimeout(() => {
setData(["Apple", "Banana", "Cherry", "Grapes"]);
setLoading(false);
}, 2500);
}, []);
return (
<div style={{ textAlign: "center", marginTop: "100px" }}>
{loading ? (
<ClipLoader color="#0078d7" size={60} />
) : (
<>
<h2>Available Fruits</h2>
<ul style={{ listStyle: "none", fontSize: "18px" }}>
{data.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</>
)}
</div>
);
}
export default App;Here, I used the ClipLoader component from react-spinners. It’s lightweight, customizable, and works perfectly for most loading scenarios.
Step 3: Customize the Spinner
You can easily adjust the spinner’s color, size, and speed using props like this:
<ClipLoader color="#28a745" size={80} speedMultiplier={1.5} />You can see the output in the screenshot below.

This flexibility allows you to match the spinner to your app’s theme and design.
Bonus Tip – Conditional Rendering with API Calls
In real-world applications, you’ll often fetch data from APIs like this:
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((data) => {
setData(data);
setLoading(false);
});
}, []);By combining this with your spinner component, you can handle loading states seamlessly across your app.
Which Method Should You Use?
- CSS Spinner: Best when you want a lightweight, fully customizable solution.
- React-Spinners Library: Ideal when you want quick, modern, and professional-looking spinners without writing CSS.
Both methods are great; it depends on whether you prefer control or convenience.
When I first implemented a loading spinner in React, I didn’t realize how much it could improve user experience. But after adding it, users immediately noticed smoother transitions and fewer “is it stuck?” moments.
So, whether you’re building a data dashboard, e-commerce app, or analytics platform, a spinner is a small detail that makes a big difference.
You may like to read:
- Create a Dynamic Component in React JS
- React Component File Structure Best Practices
- How To Create a Navbar Component in React
- Difference between React Component and React Element

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.