aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-15 17:09:13 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-15 17:26:17 +0100
commit36baf3e5725aeae00d81d3a082b3c04074e09f8e (patch)
tree34069dc40f7cd45707e8cea0a8993e94841af778 /src/utils
parentc826ad66df066b90b09009f2f4b83b56d018436e (diff)
refactor(hooks): replace useRouteChange with useOnRouteChange hook
* handle both event start and event complete * clean the effect * add tests
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/hooks/index.ts2
-rw-r--r--src/utils/hooks/use-on-route-change/index.ts1
-rw-r--r--src/utils/hooks/use-on-route-change/use-on-route-change.test.tsx69
-rw-r--r--src/utils/hooks/use-on-route-change/use-on-route-change.ts35
-rw-r--r--src/utils/hooks/use-route-change.tsx10
5 files changed, 106 insertions, 11 deletions
diff --git a/src/utils/hooks/index.ts b/src/utils/hooks/index.ts
index ad412c8..d42c32b 100644
--- a/src/utils/hooks/index.ts
+++ b/src/utils/hooks/index.ts
@@ -13,6 +13,7 @@ export * from './use-local-storage';
export * from './use-match-media';
export * from './use-mutation-observer';
export * from './use-on-click-outside';
+export * from './use-on-route-change';
export * from './use-pagination';
export * from './use-posts-list';
export * from './use-prism';
@@ -20,7 +21,6 @@ export * from './use-prism-theme';
export * from './use-reading-time';
export * from './use-redirection';
export * from './use-reduced-motion';
-export * from './use-route-change';
export * from './use-scroll-lock';
export * from './use-scroll-position';
export * from './use-scrollbar-width';
diff --git a/src/utils/hooks/use-on-route-change/index.ts b/src/utils/hooks/use-on-route-change/index.ts
new file mode 100644
index 0000000..d7f54c8
--- /dev/null
+++ b/src/utils/hooks/use-on-route-change/index.ts
@@ -0,0 +1 @@
+export * from './use-on-route-change';
diff --git a/src/utils/hooks/use-on-route-change/use-on-route-change.test.tsx b/src/utils/hooks/use-on-route-change/use-on-route-change.test.tsx
new file mode 100644
index 0000000..afcad0a
--- /dev/null
+++ b/src/utils/hooks/use-on-route-change/use-on-route-change.test.tsx
@@ -0,0 +1,69 @@
+import { describe, it } from '@jest/globals';
+import { render, screen as rtlScreen } from '@testing-library/react';
+import { userEvent } from '@testing-library/user-event';
+import Link from 'next/link';
+import nextRouterMock from 'next-router-mock';
+import { MemoryRouterProvider } from 'next-router-mock/MemoryRouterProvider';
+import {
+ type OnRouteChangeHandler,
+ useOnRouteChange,
+ type OnRouteChangeStep,
+} from './use-on-route-change';
+
+type TestComponentProps = {
+ callback: OnRouteChangeHandler;
+ href: string;
+ step?: OnRouteChangeStep;
+};
+
+const TestComponent = ({ callback, href, step }: TestComponentProps) => {
+ useOnRouteChange(callback, step);
+
+ return (
+ <MemoryRouterProvider>
+ <Link href={href}>New page</Link>
+ </MemoryRouterProvider>
+ );
+};
+
+describe('useOnRouteChange', () => {
+ it('trigger a callback when the route change event starts', async () => {
+ const cb = jest.fn();
+ const user = userEvent.setup();
+ const newPage = '/new-page';
+
+ nextRouterMock.push('/initial-page');
+
+ render(<TestComponent callback={cb} href={newPage} />);
+
+ expect(cb).not.toHaveBeenCalled();
+
+ await user.click(rtlScreen.getByRole('link'));
+
+ expect(nextRouterMock).toMatchObject({
+ asPath: newPage,
+ pathname: newPage,
+ });
+ expect(cb).toHaveBeenCalled();
+ });
+
+ it('can trigger a callback when the route change event is complete', async () => {
+ const cb = jest.fn();
+ const user = userEvent.setup();
+ const newPage = '/new-page';
+
+ nextRouterMock.push('/initial-page');
+
+ render(<TestComponent callback={cb} href={newPage} step="end" />);
+
+ expect(cb).not.toHaveBeenCalled();
+
+ await user.click(rtlScreen.getByRole('link'));
+
+ expect(nextRouterMock).toMatchObject({
+ asPath: newPage,
+ pathname: newPage,
+ });
+ expect(cb).toHaveBeenCalled();
+ });
+});
diff --git a/src/utils/hooks/use-on-route-change/use-on-route-change.ts b/src/utils/hooks/use-on-route-change/use-on-route-change.ts
new file mode 100644
index 0000000..85e7060
--- /dev/null
+++ b/src/utils/hooks/use-on-route-change/use-on-route-change.ts
@@ -0,0 +1,35 @@
+import { useRouter } from 'next/router';
+import { useEffect } from 'react';
+
+export type OnRouteChangeStep = 'start' | 'end';
+
+export type OnRouteChangeHandler = () => void;
+
+/**
+ * React hook to trigger a callback function on route change.
+ *
+ * @param {OnRouteChangeHandler} handler - The callback to trigger.
+ * @param {OnRouteChangeStep} [step] - The event step.
+ */
+export const useOnRouteChange = (
+ handler: OnRouteChangeHandler,
+ step: OnRouteChangeStep = 'start'
+) => {
+ const router = useRouter();
+
+ useEffect(() => {
+ if (step === 'end') {
+ router.events.on('routeChangeComplete', handler);
+
+ return () => {
+ router.events.off('routeChangeComplete', handler);
+ };
+ }
+
+ router.events.on('routeChangeStart', handler);
+
+ return () => {
+ router.events.off('routeChangeStart', handler);
+ };
+ }, [handler, router.events, step]);
+};
diff --git a/src/utils/hooks/use-route-change.tsx b/src/utils/hooks/use-route-change.tsx
deleted file mode 100644
index 2eff6e9..0000000
--- a/src/utils/hooks/use-route-change.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { useRouter } from 'next/router';
-import { useEffect } from 'react';
-
-export const useRouteChange = (callback: () => void) => {
- const { events } = useRouter();
-
- useEffect(() => {
- events.on('routeChangeStart', callback);
- }, [events, callback]);
-};