Official tsParticles ReactJS component
If you are using Next.js, prefer @tsparticles/nextjs for a Next-first integration layer.
npm install @tsparticles/reactor
yarn add @tsparticles/reactnpm install @tsparticles/react @tsparticles/engineor
yarn add @tsparticles/react @tsparticles/engine@tsparticles/engine is the core package for tsParticles, it contains useful types like ISourceOptions, Engine or Container.
Starting from version 1.17.0 there are two official React templates:
cra-template-particles: Simple ReactJS template with full screen particles, using JavaScriptcra-template-particles-typescript: Simple ReactJS template with full screen particles, using TypeScript
You can install them using create-react-app like this:
$ create-react-app your_app --template particlesor
$ create-react-app your_app --template particles-typescriptParticlesProvider is required and receives one async init callback.
That callback is executed only once for the app lifecycle.
Important
Place ParticlesProvider at the root of your application (e.g., main.tsx, index.jsx, or layout.tsx), not inside a component that conditionally mounts or unmounts.
The provider must be rendered only once for the entire app lifecycle. If it is placed inside a component that hides or removes its children (e.g., conditional rendering, route transitions), the engine initialization runs correctly only the first time — re-mounting with a different init callback throws an error, and re-mounting with the same callback is silently ignored, which can lead to containers not being properly managed.
Examples:
import { useMemo } from "react";
import Particles, { ParticlesProvider } from "@tsparticles/react";
// import { loadAll } from "@tsparticles/all"; // if you are going to use `loadAll`, install the "@tsparticles/all" package too.
// import { loadFull } from "tsparticles"; // if you are going to use `loadFull`, install the "tsparticles" package too.
import { loadSlim } from "@tsparticles/slim"; // if you are going to use `loadSlim`, install the "@tsparticles/slim" package too.
// import { loadBasic } from "@tsparticles/basic"; // if you are going to use `loadBasic`, install the "@tsparticles/basic" package too.
const particlesInit = async engine => {
await loadSlim(engine);
};
const App = () => {
const particlesLoaded = container => {
console.log(container);
};
const options = useMemo(
() => ({
background: {
color: {
value: "#0d47a1",
},
},
fpsLimit: 120,
interactivity: {
events: {
onClick: {
enable: true,
mode: "push",
},
onHover: {
enable: true,
mode: "repulse",
},
},
modes: {
push: {
quantity: 4,
},
repulse: {
distance: 200,
duration: 0.4,
},
},
},
particles: {
color: {
value: "#ffffff",
},
links: {
color: "#ffffff",
distance: 150,
enable: true,
opacity: 0.5,
width: 1,
},
move: {
direction: "none",
enable: true,
outModes: {
default: "bounce",
},
random: false,
speed: 6,
straight: false,
},
number: {
density: {
enable: true,
},
value: 80,
},
opacity: {
value: 0.5,
},
shape: {
type: "circle",
},
size: {
value: { min: 1, max: 5 },
},
},
detectRetina: true,
}),
[],
);
return (
<ParticlesProvider init={particlesInit}>
<Particles id="tsparticles" particlesLoaded={particlesLoaded} options={options} />
</ParticlesProvider>
);
};import { useMemo } from "react";
import Particles, { ParticlesProvider } from "@tsparticles/react";
import { type Container, type Engine, type ISourceOptions, MoveDirection, OutMode } from "@tsparticles/engine";
// import { loadAll } from "@tsparticles/all"; // if you are going to use `loadAll`, install the "@tsparticles/all" package too.
// import { loadFull } from "tsparticles"; // if you are going to use `loadFull`, install the "tsparticles" package too.
import { loadSlim } from "@tsparticles/slim"; // if you are going to use `loadSlim`, install the "@tsparticles/slim" package too.
// import { loadBasic } from "@tsparticles/basic"; // if you are going to use `loadBasic`, install the "@tsparticles/basic" package too.
const particlesInit = async (engine: Engine): Promise<void> => {
await loadSlim(engine);
};
const App = () => {
const particlesLoaded = async (container?: Container): Promise<void> => {
console.log(container);
};
const options: ISourceOptions = useMemo(
() => ({
background: {
color: {
value: "#0d47a1",
},
},
fpsLimit: 120,
interactivity: {
events: {
onClick: {
enable: true,
mode: "push",
},
onHover: {
enable: true,
mode: "repulse",
},
},
modes: {
push: {
quantity: 4,
},
repulse: {
distance: 200,
duration: 0.4,
},
},
},
particles: {
color: {
value: "#ffffff",
},
links: {
color: "#ffffff",
distance: 150,
enable: true,
opacity: 0.5,
width: 1,
},
move: {
direction: MoveDirection.none,
enable: true,
outModes: {
default: OutMode.out,
},
random: false,
speed: 6,
straight: false,
},
number: {
density: {
enable: true,
},
value: 80,
},
opacity: {
value: 0.5,
},
shape: {
type: "circle",
},
size: {
value: { min: 1, max: 5 },
},
},
detectRetina: true,
}),
[],
);
return (
<ParticlesProvider init={particlesInit}>
<Particles id="tsparticles" particlesLoaded={particlesLoaded} options={options} />
</ParticlesProvider>
);
};import Particles, { ParticlesProvider } from "@tsparticles/react";
// import { loadAll } from "@tsparticles/all"; // if you are going to use `loadAll`, install the "@tsparticles/all" package too.
// import { loadFull } from "tsparticles"; // if you are going to use `loadFull`, install the "tsparticles" package too.
import { loadSlim } from "@tsparticles/slim"; // if you are going to use `loadSlim`, install the "@tsparticles/slim" package too.
// import { loadBasic } from "@tsparticles/basic"; // if you are going to use `loadBasic`, install the "@tsparticles/basic" package too.
const particlesInit = async engine => {
await loadSlim(engine);
};
const App = () => {
const particlesLoaded = container => {
console.log(container);
};
return (
<ParticlesProvider init={particlesInit}>
<Particles id="tsparticles" url="http://foo.bar/particles.json" particlesLoaded={particlesLoaded} />
</ParticlesProvider>
);
};import Particles, { ParticlesProvider } from "@tsparticles/react";
import type { Container, Engine } from "@tsparticles/engine";
// import { loadAll } from "@tsparticles/all"; // if you are going to use `loadAll`, install the "@tsparticles/all" package too.
// import { loadFull } from "tsparticles"; // if you are going to use `loadFull`, install the "tsparticles" package too.
import { loadSlim } from "@tsparticles/slim"; // if you are going to use `loadSlim`, install the "@tsparticles/slim" package too.
// import { loadBasic } from "@tsparticles/basic"; // if you are going to use `loadBasic`, install the "@tsparticles/basic" package too.
const particlesInit = async (engine: Engine): Promise<void> => {
await loadSlim(engine);
};
const App = () => {
const particlesLoaded = (container?: Container) => {
console.log(container);
};
return (
<ParticlesProvider init={particlesInit}>
<Particles id="tsparticles" url="http://foo.bar/particles.json" particlesLoaded={particlesLoaded} />
</ParticlesProvider>
);
};| Prop | Type | Definition |
|---|---|---|
| id | string | The id of the element. |
| options | object | The options of the particles instance. |
| url | string | The remote options url, called using an AJAX request |
| style | object | The style of the canvas element. |
| className | string | The class name of the canvas wrapper. |
Find all configuration options here.
You can find sample configurations here 📖
Preset demos can be found here
There's also a CodePen collection actively maintained and updated here
Report bugs and issues here



