React Integration
Advanced patterns and best practices for using threeparticles with React.
New to R3F? Start with the R3F Quick Start guide.
Performance Tips
- Memoize configs to prevent recreation on re-renders
- Use refs for particle systems to avoid React state updates
- Dispose properly in cleanup functions
- Limit re-renders by separating particle logic from reactive state
import { useState, useRef } from "react";
import { Particles } from "@threeparticles/core";
function Game() {
const [score, setScore] = useState(0);
const particlesRef = useRef<Particles>(null);
// Update particles imperatively, not through state
function onCollect() {
setScore((s) => s + 1);
// Trigger burst without causing re-render
particlesRef.current?.start();
}
return <GameUI score={score} onCollect={onCollect} />;
}Manual Integration
If you need more control than the built-in component provides, you can manually manage the particle lifecycle:
import { useEffect, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { Particles, ParticlesConfig } from "@threeparticles/core";
function ManagedParticles({ config }: { config: ParticlesConfig }) {
const particlesRef = useRef<Particles | null>(null);
useEffect(() => {
const particles = new Particles(config);
particlesRef.current = particles;
particles.start();
return () => {
particles.stop();
particles.dispose();
};
}, [config]);
useFrame((_, delta) => {
particlesRef.current?.update(delta);
});
return particlesRef.current ? <primitive object={particlesRef.current} /> : null;
}Note: The native
<Particles>component from@threeparticles/core/reacthandles lifecycle and frame updates automatically.
Custom Hook
Create a reusable hook for particle systems outside of R3F:
import { useEffect, useRef } from "react";
import { Particles, ParticlesConfig } from "@threeparticles/core";
export function useParticles(config: ParticlesConfig) {
const particlesRef = useRef<Particles | null>(null);
useEffect(() => {
const particles = new Particles(config);
particles.start();
particlesRef.current = particles;
return () => {
particles.stop();
particles.dispose();
particlesRef.current = null;
};
}, []);
return particlesRef;
}