hooks_use-route-handler.js

import { React, ReactRouter } from '@gravityforms/libraries';

const { useEffect, useRef } = React;
const { useSearchParams } = ReactRouter;

/**
 * @module useRouteHandler
 * @description A hook that handles route changes.
 *
 * @since 4.2.0
 *
 * @param {object}   args         The arguments for the hook.
 * @param {Function} args.handler The handler function to run when the route changes.
 *
 * @return {object} The route handler state and actions.
 */
const useRouteHandler = ( { handler } = {} ) => {
	const [ searchParams, setSearchParams ] = useSearchParams();
	const prevSearchParams = useRef( searchParams );
	const runIdRef = useRef( 0 );
	const handlerRef = useRef( handler );
	handlerRef.current = handler;

	useEffect( () => {
		const fn = handlerRef.current;
		if ( ! fn ) {
			return;
		}

		const currentRunId = runIdRef.current + 1;
		runIdRef.current = currentRunId;

		const runHandler = async () => {
			await fn( {
				prevSearchParams: prevSearchParams.current,
				searchParams,
				setSearchParams,
			} );
			// Only the latest invocation may update prevSearchParams so overlapping async handlers cannot reorder it.
			if ( runIdRef.current === currentRunId ) {
				prevSearchParams.current = searchParams;
			}
		};

		try {
			runHandler();
		} catch ( error ) {
			console.error( 'Error running route handler:', error );
		}
	}, [ searchParams, setSearchParams ] );

	return {
		searchParams,
		setSearchParams,
	};
};

export default useRouteHandler;