[RFC] Add useDomTransition hook for better DX in DOM animations #33720
Replies: 4 comments 1 reply
-
Does the |
Beta Was this translation helpful? Give feedback.
-
yes its will be a great idea |
Beta Was this translation helpful? Give feedback.
-
This is an elegant shift not just a new hook, but a cleaner mental model for lifecycle aware DOM transitions. |
Beta Was this translation helpful? Give feedback.
-
The proposed useDomTransition hook would help streamline DOM animation handling in React by: Providing a declarative API for triggering animations without manually juggling useEffect and refs. Managing state-to-DOM synchronization, so animations run exactly when elements enter, update, or leave. Handling cleanup and cancellation automatically, preventing memory leaks or orphaned animations. Improving developer experience (DX) by reducing boilerplate and making animations easier to read and maintain. In practice, it could wrap around the Web Animations API or CSS transitions, exposing a simple React-friendly interface. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
[RFC] Add useDomTransition hook for better DX in DOM animations
Summary
Propose a built-in
useDomTransition
hook that leverages React 19's new useRef cleanup functionality to provide declarative DOM animations without requiring external libraries.Motivation
Current Pain Points in React DOM Animations
1. Library Dependency Hell
Currently, developers need heavy libraries for basic DOM transitions:
2. Complex State Management
Without libraries, developers resort to complex patterns:
3. Competitive Disadvantage
Svelte provides built-in animation directives (
in:
,out:
,transition:
), offering superior DX out of the box. React developers deserve the same level of built-in animation support.Detailed Design
Usage Example
const transition = useDomTransition();
return (
{show && (
<div ref={transition({
in: (element) => ({
duration: 300,
tick: (progress) => {
element.style.opacity = progress.toString();
}
}),
out: (element) => ({
duration: 300,
tick: (progress) => {
element.style.opacity = progress.toString();
}
})
})}>
Hello World! 👋
)} );
Implementation
"use client";
import { useRef, useCallback } from "react";
import { linear } from "../easing";
export interface TransitionConfig {
duration?: number;
easing?: (t: number) => number;
tick?: (t: number) => void;
}
export interface TransitionOptions {
in: (node: HTMLElement) => TransitionConfig | Promise;
out: (node: HTMLElement) => TransitionConfig | Promise;
}
// Enhanced useDomTransition - allows inline option specification
export const useDomTransition = () => {
const containerRef = useRef<HTMLElement | null>(null);
const optionsRef = useRef<TransitionOptions | null>(null);
const elementRef = useRef<HTMLElement | null>(null);
const originalNextSiblingRef = useRef<Element | null>(null);
const stableCallback = useCallback((element: HTMLElement | null) => {
if (!element || !optionsRef.current) return;
elementRef.current = element;
}, []);
// Function that receives options and returns ref callback
return (options: TransitionOptions) => {
optionsRef.current = options;
return stableCallback;
};
};
How it Works
The hook leverages React 19's new useRef cleanup capability:
in
transitionout
transitionThis approach eliminates the need for complex state management while providing smooth enter/exit animations.
Benefits
Developer Experience
Performance
Ecosystem Impact
Beta Was this translation helpful? Give feedback.
All reactions