Library / SDK
davidhu2000/react-spinners avatar
davidhu2000/react-spinners

react-spinners: a spinner component library for React, and what it does not do

A collection of loading spinner components for react

3,354 stars283 forksTypeScriptMIT

At a glance

What is it?
react-spinners ships a fixed set of SVG and CSS loading indicators as React components, with a shared prop surface and no runtime dependencies. It is a rendering library, not a loading-state manager, and the README is explicit about which props exist and which do not.
Who is it for?
Adopt react-spinners when you want a known spinner shape rendered as a React component with typed props and no extra runtime dependency, and when the built-in defaults are close enough to your design. Do not adopt it expecting a global loading orchestrator, a Suspense integration, or a theming layer; the README documents none of those, and the package has no context provider.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 9, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What react-spinners replaces, and who ends up using it

Every React app that fetches data needs something on screen between the request and the response. The common shortcut is a hand-written div with a CSS keyframe animation, copied between projects and drifting in markup each time. react-spinners replaces that with a named component per spinner shape: ClipLoader, BeatLoader, RingLoader, and the rest of the list in the README's default-values table. Each one is a React component with a typed prop surface, so the same import works in TypeScript and JavaScript projects without a separate type package.

The intended audience is a frontend developer who already has a loading boolean in component state and wants a visual for it. The README's own example is exactly that shape: a useState boolean toggled by a button, passed into ClipLoader as the loading prop. The library does not decide when to load, does not talk to your data layer, and does not know about routing or Suspense. It renders a shape when told to and renders null when told not to.

That narrowness is the point. A team that already has loading state in place can drop in a component and get a consistent indicator across screens. A team looking for something that observes fetch state and coordinates a global overlay is looking at the wrong package.

The prop contract: loading, color, cssOverride and speedMultiplier

The README lists four common default props shared by all loaders: loading defaults to true, color defaults to "#000000", cssOverride defaults to an empty object, and speedMultiplier defaults to 1. Those four are the whole customization surface unless a specific loader adds something. There is no theme object, no size scale, and no variant system.

The loading prop is a plain boolean gate. The README states that the loader renders null when loading is false, which means an unmounted spinner leaves no wrapper element behind. That matters for layout: a container that expects a child will collapse rather than hold space.

color accepts a hex hash in the format #XXXXXX or #XXX, plus a fixed list of basic color names (maroon, red, orange, yellow, olive, green, purple, white, fuchsia, lime, teal, aqua, blue, navy, black, gray, silver). It does not accept rgb(), hsl(), or CSS variables, so a design token stored as a custom property cannot be passed directly.

cssOverride is an object of camelCase styles applied as inline styles. The README notes any HTML CSS property is valid there. Because it becomes an inline style attribute, it wins over class-based rules, which is convenient for one-off adjustments and awkward if you were hoping to control spinners from a stylesheet.

speedMultiplier scales the animation speed. The README's class-component example passes 1.5 alongside size, color, loading and the aria and data attributes.

How sizing works, and where the prop table bites

size, height, width and radius accept either a number or a string. A number is treated as pixels. A string is checked against valid CSS units; if the unit is valid the value passes through unchanged, and if it is invalid the library logs a console warning and falls back to px. That fallback is worth knowing before you ship, because a typo like "2remm" produces a warning and a silently wrong size rather than a thrown error.

The README's table of per-loader defaults is the part that surprises people. BarLoader, FadeLoader and ScaleLoader have no size default at all; they are defined by height and width instead (BarLoader: height 4, width 100; FadeLoader: height 15, width 5, radius 2, margin 2; ScaleLoader: height 35, width 4, radius 2, margin 2). Passing size to those three is not part of the documented contract. Meanwhile the circular loaders (BounceLoader, CircleLoader, ClockLoader, DotLoader, HashLoader, MoonLoader, PacmanLoader, PuffLoader, RingLoader) default to size values between 25 and 60, and the small dot-style loaders (BeatLoader, GridLoader, PropagateLoader, PulseLoader, RiseLoader, RotateLoader, SyncLoader, ClimbingBoxLoader, ClipLoader) default to 15 or 35.

If you want a uniform visual weight across a page, you cannot assume one prop name works everywhere. Either standardize on loaders that share a sizing prop, or pass the right prop per loader and accept the branching.

Installing react-spinners and rendering a first loader

The README gives two install commands, one for Yarn and one for npm. The npm form uses --save, which writes the dependency into package.json.

bash
npm install --save react-spinners

With Yarn the equivalent is a single add. Either way, the package name is react-spinners and the current published version is 0.17.1.

bash
yarn add react-spinners

Once installed, import a named loader and render it. The README's example imports ClipLoader and drives it from a boolean in state, with an inline style object passed as cssOverride.

tsx
import { useState, CSSProperties } from "react";
import { ClipLoader } from "react-spinners";

const override: CSSProperties = {
  display: "block",
  margin: "0 auto",
  borderColor: "red",
};

function App() {
  let [loading, setLoading] = useState(true);
  let [color, setColor] = useState("#ffffff");
  return (
    <ClipLoader color={color} loading={loading} cssOverride={override} size={150} />
  );
}

What you should see: a 150px ClipLoader centered horizontally because of the margin rule in the override, tinted by the color state, and gone entirely from the DOM when loading flips to false.

The README also shows a class-component version that passes speedMultiplier={1.5} alongside aria-label and data-testid, which is the pattern to copy if you need to slow down or speed up the animation or target the spinner in tests.

What react-spinners does not give you

The library has no concept of a loading boundary. It will not watch a promise, a fetch call, or a Suspense resource, and the README documents no integration with any of them. You supply the boolean. In a codebase where loading state is scattered across hooks and stores, react-spinners does nothing to consolidate it, and adding it will not reduce the number of places you track whether something is in flight.

Accessibility is also left to the caller. The README notes that all valid HTML props such as aria-* and data-* are supported, and its examples pass aria-label="Loading Spinner", but nothing is applied by default. A spinner rendered without an aria-label is a decorative element with no announced status. If you need an assertive live region, you build it.

Styling has a hard edge too. Because cssOverride lands as inline styles and color only accepts hex or the listed color names, the library does not fit a design system that drives color through CSS custom properties or utility classes. The related search phrase about using react-spinners with Tailwind points at exactly this gap: the README documents no Tailwind integration, so any Tailwind-based styling has to go through inline overrides or a wrapper element you control.

Finally, the README does not document server-side rendering behavior, tree-shaking guarantees, or a rollback path if a release changes a default. Treat the prop table as the contract and verify anything outside it against the source.

react-spinners against react-loader-spinner

react-loader-spinner is the alternative that shows up most often in searches alongside this package, and the two take different approaches to the same problem. react-spinners defines each loader as its own exported component, so you import exactly the shapes you use and the prop surface is shared across all of them. react-loader-spinner's published interface centers on a single component that takes a type prop selecting the spinner variant, which means one import and a string that decides what renders. The trade-off is type safety at the call site: a per-component import lets TypeScript narrow the accepted props, while a type-string API concentrates the choice in a value that the compiler checks less precisely.

Both are React component libraries and neither manages loading state, so the choice does not change your data flow. It changes how imports look, how much of the bundle a bundler can drop, and how the prop names read at the call site. If your team already imports named components elsewhere, react-spinners is the smaller mental shift. If you would rather keep one import and switch variants with a prop, the other shape may fit better.

Licence, maintenance and the cost of upgrading

The package is MIT licensed, per the LICENSE file and the license field in package.json. MIT permits use, modification and redistribution with the copyright notice and permission notice retained; the header comment in source files and the LICENSE file are what carry that. This is a description of the licence text, not legal advice, and a team with specific redistribution questions should read the LICENSE file in the repository rather than a summary.

Maintenance is visible in the release record. v0.17.1 was released on 2026-09-06, following v0.17.0 on 2025-04-21 and v0.16.1 on 2025-04-14. The last push to the default branch was on 2026-09-18, so the repository is not archived and has seen work within the last week. The gap between v0.17.0 and v0.17.1 is roughly four and a half months, which is the cadence to plan around: this is not a package that ships weekly.

The upgrade cost is low but not zero. The published surface is a set of small components with four common props, so a minor bump is unlikely to touch your call sites. The risk sits in defaults. If a future release changes a default size, color or margin, the change lands silently in your UI because nothing in the API forces you to restate the values. Pinning the version in your lockfile and reading CHANGELOG.md before bumping is the cheap insurance. The repository also ships both CommonJS and ESM builds (main points at index.js, module at esm/index.js), so a bundler that resolves the module field gets the ESM output; verify which entry your build actually picks up before assuming tree-shaking is happening.

Editorial conclusion

Adopt react-spinners when you want a known spinner shape rendered as a React component with typed props and no extra runtime dependency, and when the built-in defaults are close enough to your design. Do not adopt it expecting a global loading orchestrator, a Suspense integration, or a theming layer; the README documents none of those, and the package has no context provider. Before committing, verify that the loader you picked accepts the props you plan to pass (BarLoader, FadeLoader and ScaleLoader use height and width rather than size), confirm that your bundler resolves the esm entry in package.json, and check which version your lockfile pins, since v0.17.0 and v0.17.1 are separate releases.

Frequently asked questions

How do I install react-spinners?

The README gives two options: npm install --save react-spinners, or yarn add react-spinners. Both install the package under the name react-spinners.

How do I use react-spinners in a component?

Import a named loader such as ClipLoader from "react-spinners" and render it with a loading boolean, a color, and optionally cssOverride and size. The README states the loader renders null when loading is false.

What is react-spinners in React.js?

It is a collection of loading spinner components for React, based on Halogen, distributed as the react-spinners package. Each loader is a component with its own default properties that you override through props.

Official sources

  1. davidhu2000/react-spinners on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/davidhu2000-react-spinners.svg)](https://hysenlabs.com/projects/davidhu2000-react-spinners)