Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Since the router.push returned from the createNavigation function is captured, the proxy cannot be applied. #1809

Closed
3 tasks done
Lee-Minhoon opened this issue Mar 23, 2025 · 0 comments
Labels
bug Something isn't working unconfirmed Needs triage.

Comments

@Lee-Minhoon
Copy link

Description

When applying a Proxy to router.push from next/navigation, the router.push function returned by createNavigation captures an outdated reference. As a result, it attempts to call a revoked function instead of the updated one.

Verifications

Mandatory reproduction URL

https://github.com/Lee-Minhoon/next-intl-proxy

Reproduction description

Since the router.push returned from the createNavigation function is captured, the proxy pattern cannot be applied.

I tested this by implementing it in the same format as next-intl's createNavigation.

import { useMemo } from "react";

import { useRouter as useNextRouter } from "next/navigation.js";

export default function createNavigation() {
  function useRouter() {
    const router = useNextRouter();

    return useMemo(() => {
      function createHandler<Fn extends (href: string) => void>(fn: Fn) {
        return function handler(href: string): void {
          fn(href);
        };
      }

      // Refers to previous values.
      console.log("push", router.push);

      return {
        ...router,
        push: createHandler(router.push),
      };
    }, [router]);
  }

  return {
    useRouter,
  };
}

Below is a code snippet demonstrating my approach. This snippet applies a Proxy to router.push.

"use client";

import { useEffect } from "react";

import { usePathname, useRouter, useSearchParams } from "next/navigation";
import nProgress from "nprogress";

import { FunctionKeys } from "@/types/common";

function applyHandler<T extends (...args: any[]) => any>(
  handler: (
    target: T,
    thisArg: ThisParameterType<T>,
    argArray: Parameters<T>
  ) => ReturnType<T>
) {
  return handler;
}

export default function NavigationProgress() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  useEffect(() => {
    const routerFns: FunctionKeys<typeof router>[] = [
      "push",
      "replace",
      "back",
      "forward",
    ];

    const originalFns = routerFns.map((fn) => router[fn]);
    const revokeFns = routerFns.map((fn) => {
      const { proxy, revoke } = Proxy.revocable(router[fn], {
        apply: applyHandler((target, thisArg, argArray) => {
          if (fn === "push" || fn === "replace") {
            if (
              argArray[0] ===
              window.location.pathname + window.location.search
            ) {
              return;
            }
          }
          nProgress.start();
          return Reflect.apply(target, thisArg, argArray);
        }),
      });
      router[fn] = proxy as any;
      return revoke;
    });
    console.log("new push", router.push);

    return () => {
      revokeFns.forEach((revoke) => revoke());
      originalFns.forEach((fn, i) => {
        router[routerFns[i]] = fn as any;
      });
    };
  }, [router]);

  useEffect(() => {
    nProgress.done();
  }, [pathname, searchParams]);

  return null;
}

However, the router.push function created in createNavigation captures the previous value, causing it to reference a revoked function.

I expected that proxying the router from next/navigation would work seamlessly with next-intl, but that wasn't the case.

Expected behaviour

Proxying the router from next/navigation should work seamlessly with next-intl, ensuring that router.push does not retain a stale reference and operates as expected.

@Lee-Minhoon Lee-Minhoon added bug Something isn't working unconfirmed Needs triage. labels Mar 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working unconfirmed Needs triage.
Projects
None yet
Development

No branches or pull requests

1 participant