How to load until after router ends executing?
Unanswered
Buff-collared Nightjar posted this in #help-forum
Buff-collared NightjarOP
Aim:
I have a button that should start "loading spinner" when the user clicks on the button, and should stop the loading spinner when the page that the router takes mounts.
Environment:
- Nextjs v14
- App router
My attempt:
Current result: When the user clicks on the button, then the router jumps to the page, and the button never enters the "processing" state.
I have a button that should start "loading spinner" when the user clicks on the button, and should stop the loading spinner when the page that the router takes mounts.
Environment:
- Nextjs v14
- App router
My attempt:
'use client';
import { useState } from 'react';
import { Button, ButtonProps } from './ui/button';
import { useRouter } from 'next/navigation';
interface ButtonWithLinkProcessingProps extends ButtonProps {
href: string;
children: React.ReactNode;
}
export function ButtonWithLinkProcessing({
href,
children,
...props
}: ButtonWithLinkProcessingProps) {
const [isProcessing, setIsProcessing] = useState(false);
const router = useRouter();
return (
<Button
onClick={async (e) => {
e.preventDefault();
setIsProcessing(true);
await router.push(href);
setIsProcessing(false);
}}
isProcessing={isProcessing}
{...props}
>
{children}
</Button>
);
}Current result: When the user clicks on the button, then the router jumps to the page, and the button never enters the "processing" state.
4 Replies
Buff-collared NightjarOP
when I remove
setIsProcessing(false);, then I get the expected result. However, removing that function call also creates some unexpected behaviour (e.g., never ending spinner)Buff-collared NightjarOP
i solved it by using "useTransition" hook
'use client';
import { useTransition } from 'react';
import { Button, ButtonProps } from './ui/button';
import { useRouter } from 'next/navigation';
interface ButtonWithLinkProcessingProps extends ButtonProps {
href: string;
children: React.ReactNode;
}
export function ButtonWithLinkProcessing({
href,
children,
...props
}: ButtonWithLinkProcessingProps) {
const [isProcessing, startTransition] = useTransition();
const router = useRouter();
return (
<Button
onClick={(e) => {
e.preventDefault();
startTransition(() => {
router.push(href);
});
}}
isProcessing={isProcessing}
{...props}
>
{children}
</Button>
);
}