aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks/use-redirection
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/hooks/use-redirection')
-rw-r--r--src/utils/hooks/use-redirection/index.ts1
-rw-r--r--src/utils/hooks/use-redirection/use-redirection.test.ts80
-rw-r--r--src/utils/hooks/use-redirection/use-redirection.ts41
3 files changed, 122 insertions, 0 deletions
diff --git a/src/utils/hooks/use-redirection/index.ts b/src/utils/hooks/use-redirection/index.ts
new file mode 100644
index 0000000..c81c82c
--- /dev/null
+++ b/src/utils/hooks/use-redirection/index.ts
@@ -0,0 +1 @@
+export * from './use-redirection';
diff --git a/src/utils/hooks/use-redirection/use-redirection.test.ts b/src/utils/hooks/use-redirection/use-redirection.test.ts
new file mode 100644
index 0000000..c14ac4c
--- /dev/null
+++ b/src/utils/hooks/use-redirection/use-redirection.test.ts
@@ -0,0 +1,80 @@
+import { describe, it } from '@jest/globals';
+import { renderHook } from '@testing-library/react';
+import nextRouterMock from 'next-router-mock';
+import { MemoryRouterProvider } from 'next-router-mock/MemoryRouterProvider';
+import { useRedirection } from './use-redirection';
+
+describe('useRedirection', () => {
+ it('redirects to another page', async () => {
+ const initialPath = '/initial-path';
+ const redirectPath = '/redirect-path';
+
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+ expect.assertions(2);
+
+ await nextRouterMock.push('/initial-path');
+
+ expect(nextRouterMock.asPath).toBe(initialPath);
+
+ renderHook(() => useRedirection({ to: redirectPath }), {
+ wrapper: MemoryRouterProvider,
+ });
+
+ expect(nextRouterMock.asPath).toBe(redirectPath);
+ });
+
+ it('can replace the url in the history', async () => {
+ const initialPath = '/initial-path';
+ const redirectPath = '/redirect-path';
+
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+ expect.assertions(2);
+
+ await nextRouterMock.push('/initial-path');
+
+ expect(nextRouterMock.asPath).toBe(initialPath);
+
+ renderHook(() => useRedirection({ isReplacing: true, to: redirectPath }), {
+ wrapper: MemoryRouterProvider,
+ });
+
+ expect(nextRouterMock.asPath).toBe(redirectPath);
+
+ /* Ideally we should check if when we use `back()` the current path is
+ * still the redirectPath but it is not yet implemented in the mock. */
+ });
+
+ it('can conditionally redirect to another page', async () => {
+ const paths = {
+ initial: '/initial-path',
+ matching: '/matching-path',
+ redirect: '/redirect-path',
+ };
+
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+ expect.assertions(3);
+
+ await nextRouterMock.push('/initial-path');
+
+ expect(nextRouterMock.asPath).toBe(paths.initial);
+
+ const { rerender } = renderHook(
+ () =>
+ useRedirection({
+ to: paths.redirect,
+ whenPathMatches: (path) => path === paths.matching,
+ }),
+ {
+ wrapper: MemoryRouterProvider,
+ }
+ );
+
+ expect(nextRouterMock.asPath).toBe(paths.initial);
+
+ await nextRouterMock.push(paths.matching);
+
+ rerender();
+
+ expect(nextRouterMock.asPath).toBe(paths.redirect);
+ });
+});
diff --git a/src/utils/hooks/use-redirection/use-redirection.ts b/src/utils/hooks/use-redirection/use-redirection.ts
new file mode 100644
index 0000000..1592a33
--- /dev/null
+++ b/src/utils/hooks/use-redirection/use-redirection.ts
@@ -0,0 +1,41 @@
+import { useRouter } from 'next/router';
+import { useEffect } from 'react';
+
+export type UseRedirectionConfig = {
+ /**
+ * Should the url be replaced in the history?
+ *
+ * @default false
+ */
+ isReplacing?: boolean;
+ /**
+ * The destination.
+ */
+ to: string;
+ /**
+ * Redirect only when the current path matches the condition.
+ *
+ * @param {string} path - The current slug.
+ * @returns {boolean} True if the path matches.
+ */
+ whenPathMatches?: (path: string) => boolean;
+};
+
+export const useRedirection = ({
+ isReplacing = false,
+ to,
+ whenPathMatches,
+}: UseRedirectionConfig) => {
+ const router = useRouter();
+
+ useEffect(() => {
+ const shouldRedirect = whenPathMatches
+ ? whenPathMatches(router.asPath)
+ : true;
+
+ if (shouldRedirect) {
+ if (isReplacing) router.replace(to, undefined, { shallow: true });
+ else router.push(to);
+ }
+ }, [isReplacing, router, to, whenPathMatches]);
+};