Optimizing Framer Motion animations.
useMotionValue for Direct Updates
jsximport { motion, useMotionValue, useTransform } from 'framer-motion'; // ❌ Re-renders on every update function BadSlider() { const [x, setX] = useState(0); return ( <motion.div drag="x" onDrag={(_, info) => setX(info.point.x)} /> ); } // ✅ No re-renders, direct DOM updates function GoodSlider() { const x = useMotionValue(0); return ( <motion.div drag="x" style={{ x }} /> ); }
useTransform for Derived Values
jsxfunction ParallaxCard() { const x = useMotionValue(0); // Derived values update without re-render const rotate = useTransform(x, [-200, 200], [-30, 30]); const opacity = useTransform(x, [-200, 0, 200], [0.5, 1, 0.5]); const background = useTransform( x, [-200, 0, 200], ['#ff0000', '#00ff00', '#0000ff'] ); return ( <motion.div drag="x" style={{ x, rotate, opacity, background }} dragConstraints={{ left: -200, right: 200 }} /> ); }
useSpring for Smooth Values
jsximport { useSpring, useMotionValue } from 'framer-motion'; function SmoothFollower() { const x = useMotionValue(0); const smoothX = useSpring(x, { stiffness: 100, damping: 20, }); return ( <> <motion.div drag="x" style={{ x }} className="leader" /> <motion.div style={{ x: smoothX }} className="follower" /> </> ); }
Reduce Motion Preference
jsximport { useReducedMotion } from 'framer-motion'; function AccessibleAnimation() { const shouldReduceMotion = useReducedMotion(); return ( <motion.div animate={{ x: 100 }} transition={{ duration: shouldReduceMotion ? 0 : 0.5, }} /> ); } // Or apply globally function App() { const shouldReduceMotion = useReducedMotion(); return ( <MotionConfig reducedMotion="user"> {/* Your app */} </MotionConfig> ); }
Lazy Loading Animations
jsximport { LazyMotion, domAnimation, m } from 'framer-motion'; // Only load animation features when needed function App() { return ( <LazyMotion features={domAnimation}> <m.div animate={{ opacity: 1 }} /> </LazyMotion> ); } // Even more minimal import { LazyMotion, domMax } from 'framer-motion'; function App() { return ( <LazyMotion features={domMax} strict> {/* Full features, loaded lazily */} </LazyMotion> ); }
Avoid Re-renders During Animation
jsx// ❌ Bad: State changes cause re-renders function BadAnimation() { const [scale, setScale] = useState(1); useEffect(() => { const interval = setInterval(() => { setScale((s) => (s === 1 ? 1.2 : 1)); }, 500); return () => clearInterval(interval); }, []); return <motion.div animate={{ scale }} />; } // ✅ Good: Use variants or motion values function GoodAnimation() { return ( <motion.div animate={{ scale: [1, 1.2, 1] }} transition={{ repeat: Infinity, duration: 1 }} /> ); }