nextjs-router-events
Version:
A router events alternative for Next.js 13+ with app directory with the ability to prevent user navigation.
63 lines (62 loc) • 2.65 kB
JavaScript
'use client';
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var _this = this;
import { useEffect, useRef, useState } from 'react';
import { useRouter as usePrimitiveRouter } from 'next/navigation';
import { triggerBeforeRouteChangeEvent, triggerRouteChangeStartEvent } from './events';
import { useFreezeRequestsContext } from './context';
var createRouterProxy = function (router, isFrozen, signal) {
return new Proxy(router, {
get: function (target, prop, receiver) {
if (prop === 'push') {
return function (href, options) {
var resolvePush = function () {
triggerRouteChangeStartEvent(href);
Reflect.apply(target.push, _this, [href, options]);
};
if (isFrozen) {
window.addEventListener('routeChangeConfirmationEvent', function (ev) {
if (ev.detail.targetUrl === href)
resolvePush();
}, { signal: signal });
triggerBeforeRouteChangeEvent(href); // NOTE: may wanna use a timeout here
return;
}
resolvePush();
};
}
return Reflect.get(target, prop, receiver);
},
});
};
export var useRouter = function () {
var router = usePrimitiveRouter();
var freezeRequests = useFreezeRequestsContext().freezeRequests;
var abortControllerRef = useRef(new AbortController());
var _a = __read(useState(createRouterProxy(router, freezeRequests.length !== 0, abortControllerRef.current.signal)), 2), routerProxy = _a[0], setRouterProxy = _a[1];
useEffect(function () {
return function () { return abortControllerRef.current.abort(); };
}, []);
useEffect(function () {
abortControllerRef.current.abort();
var abortController = new AbortController();
setRouterProxy(createRouterProxy(router, freezeRequests.length !== 0, abortController.signal));
return function () { return abortController.abort(); };
}, [router, freezeRequests]);
return routerProxy;
};