From 47d2dfdb5472e14320fe7e824cc680b6f28b58bc Mon Sep 17 00:00:00 2001 From: Miroslav Petrov <46135319+petrovmiroslav@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:40:16 +0200 Subject: [PATCH] Update examples/active-class-name (#62506) ### Description The current implementation of the activeClassName example doesn't support the `UrlObject` type for the "href" Link prop. For example ``` Dynamic Route ``` won't work. ### Suggestion We can use the `resolveHref` function to handle all cases. Co-authored-by: Sam Ko --- .../components/ActiveLink.tsx | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/examples/active-class-name/components/ActiveLink.tsx b/examples/active-class-name/components/ActiveLink.tsx index 6bae8c9639..472ab98ea6 100644 --- a/examples/active-class-name/components/ActiveLink.tsx +++ b/examples/active-class-name/components/ActiveLink.tsx @@ -1,6 +1,26 @@ import { useRouter } from "next/router"; import Link, { LinkProps } from "next/link"; -import React, { PropsWithChildren, useState, useEffect } from "react"; +import React, { PropsWithChildren, useEffect, useState } from "react"; +import { NextRouter } from "next/src/shared/lib/router/router"; +import { resolveHref } from "next/dist/client/resolve-href"; + +const getLinkUrl = (params: { + router: NextRouter; + href: LinkProps["href"]; + as: LinkProps["as"]; +}): string => { + // Dynamic route will be matched via props.as + // Static route will be matched via props.href + if (params.as) return resolveHref(params.router, params.as); + + const [resolvedHref, resolvedAs] = resolveHref( + params.router, + params.href, + true, + ); + + return resolvedAs || resolvedHref; +}; type ActiveLinkProps = LinkProps & { className?: string; @@ -13,21 +33,22 @@ const ActiveLink = ({ className, ...props }: PropsWithChildren) => { - const { asPath, isReady } = useRouter(); + const router = useRouter(); const [computedClassName, setComputedClassName] = useState(className); useEffect(() => { // Check if the router fields are updated client-side - if (isReady) { - // Dynamic route will be matched via props.as - // Static route will be matched via props.href - const linkPathname = new URL( - (props.as || props.href) as string, - location.href, - ).pathname; + if (router.isReady) { + const linkUrl = getLinkUrl({ + router, + href: props.href, + as: props.as, + }); + + const linkPathname = new URL(linkUrl, location.href).pathname; // Using URL().pathname to get rid of query and hash - const activePathname = new URL(asPath, location.href).pathname; + const activePathname = new URL(router.asPath, location.href).pathname; const newClassName = linkPathname === activePathname @@ -39,8 +60,7 @@ const ActiveLink = ({ } } }, [ - asPath, - isReady, + router, props.as, props.href, activeClassName,