skip to Main Content

It’s my loginButton which is the wrapper of Button component in another file.

'use client';

import { useRouter } from 'next/navigation';
import { useTransition } from 'react';

interface LoginButtonProps {
  children: React.ReactNode;
  mode?: 'modal' | 'redirect';
  asChild?: boolean;
}

export const LoginButton = ({
  children,
  mode = 'redirect',
  asChild,
}: LoginButtonProps) => {
  const router = useRouter();
  const [isPending, startTransition] = useTransition();

  const onclickHandler = () => {
    router.push('/auth/login');
    console.log('clicked');
  };

  return (
    <span className="cursor-pointer" onClick={onclickHandler}>
      {children}
    </span>
  );
};

and the Button component is:

import { Button } from '@/components/ui/button';
import { LoginButton } from '@/components/auth/login-button';

export default function Home() {
  return (
    <main>
        <LoginButton>
          <Button variant="secondary" size="lg" className="mt-8">
            Sign in
          </Button>
        </LoginButton>
      </div>
    </main>
  );
}

I want to pass the isPending state as prop and use inside Home component. I want to keep the button disabled while isPending is true as well as change its text. how to achieve this?

Please help me with your valuable time and knowledge. Thanks in advance.

2

Answers


  1. You can try passing a fallback component to the LoginButton that will be rendered while the transition is pending.

    Login Button:

    export const LoginButton = ({
      children,
      mode = 'redirect',
      asChild,
      fallback
    }: LoginButtonProps) => {
      const router = useRouter();
      const [isPending, startTransition] = useTransition();
    
      const onclickHandler = () => {
        router.push('/auth/login');
        console.log('clicked');
      };
    
      return (
        <span className="cursor-pointer" onClick={onclickHandler}>
          {isPending ? fallback : children}
        </span>
      );
    };
    

    Fallback Component:

    function LoadingBtn() {
     return (
       <Button variant="secondary" size="lg" className="mt-8" disabled>
          Loading
       </Button>
     )
    }
    

    Implementation:

    <LoginButton fallback={<LoadingBtn />}>
              <Button variant="secondary" size="lg" className="mt-8">
                Sign in
              </Button>
    </LoginButton>
    
    Login or Signup to reply.
  2. You can pass a function (instead of a react element) as children of LoginButton

    export default function Home() {
      return (
        <main>
            <LoginButton>
              {disabled => ( 
                <Button 
                  variant="secondary" 
                  size="lg" 
                  className="mt-8" 
                  disabled={disabled}
                >
                  Sign in
                </Button>
              )}
            </LoginButton>
          </div>
        </main>
      );
    }
    

    and call this function in LoginButton component

    
    export const LoginButton = ({children}) => {
      const [isPending, startTransition] = useTransition();
    
      ...  
    
      return (
        <span className="cursor-pointer" onClick={onclickHandler}>
          {children(isPending)}
        </span>
      );
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search