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

Potentially simpler Link wrapper implementation? #14

Open
musjj opened this issue Aug 14, 2024 · 0 comments
Open

Potentially simpler Link wrapper implementation? #14

musjj opened this issue Aug 14, 2024 · 0 comments

Comments

@musjj
Copy link

musjj commented Aug 14, 2024

I was playing around with my own progress bar implementation while referencing this library, and I discovered that you don't actually have to call startProgress in the same callback with the task you're trying to track:

"use client";

import NextLink from "next/link";
import {
  type ComponentPropsWithoutRef,
  forwardRef,
  startTransition,
} from "react";
import { useProgress } from "react-transition-progress";

export const Link = forwardRef<
  HTMLAnchorElement,
  ComponentPropsWithoutRef<typeof NextLink>
>(({ onClick, ...props }, ref) => {
  const startProgress = useProgress();

  return (
    <NextLink
      ref={ref}
      onClick={(e) => {
        onClick?.(e);
        startTransition(startProgress);
      }}
      {...props}
    />
  );
});

Link.displayName = "Link";

I have no idea why this even works though. I tested it with heavy network throttling and everything seems perfectly sound.

If this is actually a good approach, it would eliminate the need to duplicate Link's logic (like the current URL formatter).

Would appreciate more eyes on this though (and maybe an explanation too).

EDIT: Also works for submit buttons in server action forms:

button.tsx

"use client";

export const Button = forwardRef<
  HTMLButtonElement,
  ComponentPropsWithoutRef<"button">
>(({ onClick, ...props }, ref) => {
  const startProgress = useProgress();

  return (
    <button
      ref={ref}
      onClick={(e) => {
        onClick?.(e);
        startTransition(startProgress);
      }}
      {...props}
    />
  );
});

Button.displayName = "Button";

page.tsx

export default function Page() {
  return (
    <form
      action={async () => {
        "use server";
        // Play with the timeout value below to test if progress bar is accurate
        await new Promise((r) => setTimeout(r, 7000));
      }}
    >
      <Button type="submit">Submit!</Button>
    </form>
  );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant