Skip to content

Instantly share code, notes, and snippets.

@hunghg255
Created January 4, 2025 06:23
Show Gist options
  • Save hunghg255/c5295bc657703d5c976c76688968a12d to your computer and use it in GitHub Desktop.
Save hunghg255/c5295bc657703d5c976c76688968a12d to your computer and use it in GitHub Desktop.
Fix Interactive next paint INP
import { useEffect, useLayoutEffect } from 'react';
export function interactionResponse(): Promise<unknown> {
return new Promise((resolve) => {
setTimeout(resolve, 100); // Fallback for the case where the animation frame never fires.
requestAnimationFrame(() => {
setTimeout(resolve, 0);
});
});
}
/**
* Yields to main thread before continuing execution.
* If priority is 'user-blocking', it will asynchronously resolve in older browsers.
* @param {object} options - see [https://github.com/WICG/scheduling-apis/blob/main/explainers/yield-and-continuation.md](spec)
*/
export function yieldToMain(options?: any) {
if ('scheduler' in window) {
// @ts-ignore
if ('yield' in scheduler) {
// @ts-ignore
return scheduler.yield(options);
}
// @ts-ignore
if ('postTask' in scheduler) {
// @ts-ignore
return scheduler.postTask(() => {}, options);
}
}
// `setTimeout` could suffer from being delayed for longer - so for browsers not supporting yield,
// we guarantee execution for high priority actions, but it doesn't yield as trade-off.
if (options?.priority === 'user-blocking') {
return Promise.resolve();
}
return new Promise((resolve) => {
setTimeout(resolve, 100); // Fallback for the case where the animation frame never fires.
requestAnimationFrame(() => {
setTimeout(resolve, 0);
});
});
}
/**
* Returns a promise that resolves in the next frame.
*/
const runAfterPaint = async (fn: any) => {
await yieldToMain({
priority: 'background',
});
return fn();
};
export function useAfterPaintEffect(useEffectFn: any, deps: any) {
useEffect(() => {
const runPromise = runAfterPaint(useEffectFn);
return () => {
(async () => {
const cleanup = await runPromise;
if (!cleanup) {
return;
}
runAfterPaint(cleanup);
})();
};
}, deps);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment