Code
// animated-number.tsx
"use client";
import { motion, useSpring, useTransform } from "framer-motion";
import { useEffect } from "react";
function AnimatedNumber({ value }: { value: number }) {
let spring = useSpring(value, { mass: 0.8, stiffness: 75, damping: 15 });
let display = useTransform(spring, (current) =>
Math.round(current).toLocaleString()
);
useEffect(() => {
spring.set(value);
}, [spring, value]);
return <motion.span>{display}</motion.span>;
}
Usage
Works in both Client Components and Server Components.
// client-component.tsx
"use client";
export default function Page() {
let [value, setValue] = useState(1000);
return (
<div>
<button onClick={() => setValue(value - 100)}>-100</button>
<AnimatedNumber value={value} />
<button onClick={() => setValue(value + 100)}>+100</button>
</div>
);
}
// server-component.tsx
export default async function Page() {
let visitors = await getVisitors();
return (
<div>
<p>Visitors:<p>
<AnimatedNumber value={visitors} />
</div>
);
}