nehat khan
nehat khan

Reputation: 131

Next js 14 client component not showing loading button nested inside server component

hey guys I am creating a booking app with Next js 14, I have route called /search-result which shows all the events fetched from backend as a server component. I am rendering some card inside this page which is client component, and each cards have book now button which redirect the user to the /booking page after storing the clicked item data in the cookies. code.

const BookingHandler =  (data:any)=>{
        setLoading(true)
    
    const bookingSessing = {
        from: parameters?.from,
        where: parameters?.where,
        travel_date: item?.travel_date,
        arrival_time: item?.arrival_time,
        departure_time: item?.departure_time,
        passengers: parameters?.passengers,
        shipper: data?.shipper,
        seatclass: data?.class,
        ship_id: data?.ship_id,
        class_id: data?.class_id,
        schedule_id: data?.schedule_id,
        price: data?.price,
        token: token,
    }

    let encryptBookingSession = encryptdata(JSON.stringify(bookingSessing))
    setCookie('bookingSession', encryptBookingSession);
    router.push(`/booking`, )
    
    setLoading(false)
    
}

and this is the button component with onClick function.

<Button size='sm' onClick={() => BookingHandler(_i)}>
       {Loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}                                       
       Book
</Button> 

Now the problem is I am facing that, when the button gets click, it takes around 1 or 2 second to respond and than redirect the user to /booking page. and loading spinner does not also. when I make the status of Loading status to true it does loading spinner but with onclick event its not showing.

The code I share is the client component inside the /search-result page. here is the full page code.

    import Header from '@/components/Header'
import SearchForm from '@/components/SearchForm'
import FerryCards from '@/components/cards/FerryCards'
import { fetchFerry } from '@/lib/network-request/fetchFerry'
import React from 'react'



type SearchParam = {
  from: string,
  where: string,
  departure: string,
  passengers: string,

}


type SearchParamPops = {
  searchParams: SearchParam
}

type FerryData = {
  travel_date: string;
  departure_time: string;
  arrival_time: string;
  options: object;
};



const page = async ({ searchParams }: SearchParamPops) => {
  const parameters = {
    from: searchParams.from,
    where: searchParams.where,
    departure: searchParams.departure,
    passengers: searchParams.passengers

  }
  const response: any = await fetchFerry(parameters.from, parameters.where, parameters.departure, parameters.passengers)


  response?.data?.sort((a: FerryData, b: FerryData) => {
    return parseInt(a?.departure_time?.replace(":", "")) - parseInt(b?.departure_time?.replace(":", ""));
  });


  return (
    <>
    <Header/>
    <section>
      <div className="mx-auto max-w-7xl p-6 lg:px-8">
        <h1 className="text-4xl font-bold pb-3">Your Trip Results</h1>

        <h2 className="pb-3">
          Date of trip:
          <span className="italic ml-2">
            {parameters.departure}
          </span>
        </h2>
        <hr className="mb-5" />
        <h3 className="font-semibold text-xl">
          {response?.data?.length} results found
        </h3>
        <div className="space-y-2 mt-5">
          {response?.data?.map((item: any, index: number) => {
            return (
              <FerryCards key={index} item={item} parameters={parameters} token={response?.token} />
            )
          })}
        </div>
      </div>
    </section>
    </>
  )
}

export default page

the booking handler function which I have given above is inside the FerryCards component. what could be wrong I am doing here.

Upvotes: 0

Views: 669

Answers (1)

AL Faiz Ahmed
AL Faiz Ahmed

Reputation: 332

Does your <Button/> component accept the onClick prop because you are using a component and not the built-in button tag, If it accepts onClick Prop, then

Try this

<Button
  size="sm"
  onClick={() => {
    setLoading(true);
    // you function should start with small letter 
    bookingHandler(_i);
  }}
>
  {Loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
  Book
</Button> 
const BookingHandler =  (data:any)=>{

// your all logic and then setLoading to false
...

setLoading(curretnState =>  false)
}

Upvotes: 1

Related Questions