React / React Transitions / Custom Hook Transitions
Home /React /React Transitions /Custom Hook Transitions

Custom Hook Transitions

Custom Hook Transitions

For full control, build your own transition hooks using requestAnimationFrame, the Web Animations API (WAAPI), or a library like GSAP behind a React interface.

1. useSpring: Simple Value Interpolation

useSpring.js
CUSTOM HOOK

import { useState, useEffect, useRef } from 'react';

export function useSpring(target, { stiffness = 120, damping = 14 } = {}) {
  const [value, setValue] = useState(target);
  const state = useRef({ pos: target, vel: 0, raf: null });

  useEffect(() => {
    function tick() {
      const s = state.current;
      const spring = -stiffness * (s.pos - target);
      const damp   = -damping * s.vel;
      s.vel += (spring + damp) / 60;
      s.pos += s.vel / 60;

      setValue(s.pos);

      if (Math.abs(s.pos - target) > 0.01 || Math.abs(s.vel) > 0.01) {
        s.raf = requestAnimationFrame(tick);
      } else {
        s.pos = target;
        setValue(target);
      }
    }
    state.current.raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(state.current.raf);
  }, [target, stiffness, damping]);

  return value;
}

// Usage
function Knob({ value }) {
  const animated = useSpring(value);
  return <div style={{ transform: `translateX(${animated}px)` }} />;
}

2. GSAP with React (useGSAP hook)

GSAPCard.jsx
JSX + GSAP

import { useRef } from 'react';
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';

export function GSAPCard() {
  const container = useRef();

  useGSAP(() => {
    gsap.from('.card', {
      opacity: 0,
      y: 40,
      stagger: 0.12,
      duration: 0.6,
      ease: 'power3.out',
    });
  }, { scope: container });   // scoped to this component

  return (
    <div ref={container}>
      <div className="card">Card 1</div>
      <div className="card">Card 2</div>
      <div className="card">Card 3</div>
    </div>
  );
}