Skip to content

Instantly share code, notes, and snippets.

@jacob-ebey
Last active February 3, 2025 13:25
Show Gist options
  • Save jacob-ebey/3b4273fff076a9f5e1d556c49bfcc164 to your computer and use it in GitHub Desktop.
Save jacob-ebey/3b4273fff076a9f5e1d556c49bfcc164 to your computer and use it in GitHub Desktop.
useTransitonOnValueChange
import { useEffect, useRef } from "react";
export function useTransitonOnValueChange(value: unknown) {
if (!document.startViewTransition) return;
const lastValueRef = useRef(value);
const deferredRef = useRef<Deferred<void> | null>(null);
const viewTransitionRef = useRef<ViewTransition | null>(null);
if (lastValueRef.current !== value) {
lastValueRef.current = value;
if (!viewTransitionRef.current) {
if (!deferredRef.current) {
deferredRef.current = new Deferred();
}
const promise = deferredRef.current.promise;
viewTransitionRef.current = document.startViewTransition(() => promise);
viewTransitionRef.current.finished.finally(() => {
viewTransitionRef.current = null;
});
}
}
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
if (deferredRef.current) {
deferredRef.current.resolve();
}
}, [value]);
}
class Deferred<T> {
public promise: Promise<T>;
public resolve!: (value: T) => void;
public reject!: (reason?: unknown) => void;
constructor() {
this.promise = new Promise<T>((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment