How to make a component with a swiper rendered on the server side?

194 Views Asked by At

I'm currently learning next js and writing my pet project: a clothing store.

And I have a question about CSR, SSR and SSG. I have this component (Hero.tsx):

'use client'

import React, { use } from 'react'
import styles from './hero.module.scss'
import { SwiperSlide } from 'swiper/react'

import HeroSlide from './HeroSlide';
import { PromoAction } from '@/Repository/Models/PromoAction';
import HeroSwiper from './HeroSwiper';
import { fetchHeroes } from '@/Repository/Hooks/hero-hooks';
import { GENDER } from '@/shared/lib/Enums/Enums';

interface IHeroProps { 
  gender: GENDER
}

const Hero = ({ gender }: IHeroProps) => {
  const res = use(fetchHeroes(gender))
  
  return (
    <section className={styles.hero_container}>
        <HeroSwiper>
          {
            (res ? res : []).map((item: PromoAction) => {
              return <SwiperSlide key={item.id}>
                <HeroSlide 
                  imageSrc={item.image.startsWith('/') ? item.image : `/${item.image}`}
                  alt={item.name}
                  heroInfoTitle={item.name}
                  heroInfoDesc={item.description}
                  link={item.slug}
                  productImageSrc={item.products?.[0]?.images?.[0]?.startsWith('/') ? item.products?.[0]?.images?.[0] : `/${item.products?.[0]?.images?.[0]}`}
                />
              </SwiperSlide>
            })
          }
        </HeroSwiper>
    </section>
  )
}

export default Hero

In this component I am using swiper-js library and HeroSwiper component which looks like this:

'use client'

import React, { useRef, useState } from 'react'
import { Swiper } from 'swiper/react'
import { Autoplay, EffectFade } from 'swiper/modules';
import styles from './heroswiper.module.scss'

import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import 'swiper/css/scrollbar';
import "swiper/css/effect-fade";

interface IHeroSwiper {
  children: React.ReactNode
}

const HeroSwiper = ({ children }: IHeroSwiper) => {
  const progressCircle = useRef<any>(null);
  const progressContent = useRef<any>(null);
  const onAutoplayTimeLeft = (s: any, time: number, progress: number) => {
    if (progressCircle.current && progressCircle.current.style) {
      progressCircle.current.style.setProperty('--progress', 1 - progress);
    }
    if (progressContent.current) {
      progressContent.current.textContent = `${Math.ceil(time / 1000)}s`;
    }
  };
  const [activeIndex, setActiveIndex] = useState(0)
  
  return (
    <Swiper
      spaceBetween={30}
      centeredSlides={true}
      effect={"fade"}
      fadeEffect={{ crossFade: true }}
      speed={1000}
      autoplay={{
        delay: 10000,
        disableOnInteraction: false
      }}
      loop={true}
      modules={[Autoplay, EffectFade]}
      onAutoplayTimeLeft={onAutoplayTimeLeft}
      className={styles.swiper_container}
      onActiveIndexChange={(element) => setActiveIndex(element.realIndex)}
    >
      { children }
      <div className={styles.autoplay_container} slot="container-end">
        <svg className={styles.main} viewBox="0 0 48 48" ref={progressCircle}>
          <circle cx="24" cy="24" r="20"></circle>
        </svg>
        <svg className={styles.dummy} viewBox="0 0 48 48">
          <circle cx="24" cy="24" r="20"></circle>
        </svg>
        <span>{ activeIndex + 1 }</span>
      </div>
    </Swiper>
    )
}

export default HeroSwiper

As I understand all my component will be rendered on client side. But suppose if I make a new component HeroWrapper, and fetch data in it, and then pass them as props to Hero component, the data will be fetched on the server or client side? Something like this:

import React, { use } from 'react'
import Hero from './Hero'
import { GENDER } from '@/shared/lib/Enums/Enums'
import { fetchHeroes } from '@/Repository/Hooks/hero-hooks'

interface IHeroWrapper {
  gender: GENDER
}

const HeroWrapper = ({ gender }: IHeroWrapper) => {
  const res = use(fetchHeroes(gender))

  return (
    <Hero gender={gender} heroData={res} />
  )
}

export default HeroWrapper

And Hero component:

interface IHeroProps { 
  gender: GENDER
  heroData: PromoAction[]
}

const Hero = ({ gender, heroData }: IHeroProps) => {
  // const res = use(fetchHeroes(gender))
  
  return (
    <section className={styles.hero_container}>
        <HeroSwiper>
          {
            (heroData ? heroData : []).map((item: PromoAction) => {
              return <SwiperSlide key={item.id}>
.......

fetchHeroes function looks like this:

import { graphQLClient } from "@/config/graphQLClient"
import { GENDER } from "@/shared/lib/Enums/Enums"
import { getAllPromosRequest } from "@/shared/lib/GraphQL/Hero/queries"
import { useQuery } from "@tanstack/react-query"
import { PromoAction } from "../Models/PromoAction"

export const fetchHeroes = async (gender: GENDER, skip: number = 0, take: number = 10): Promise<PromoAction[]> => {
  const response: any = await graphQLClient.request(getAllPromosRequest(skip, take, gender))
  return response.getAllPromoActions
}

export default function useGetHeroesQuery(gender: GENDER, skip: number = 0, take: number = 10) {
  return useQuery({ queryKey: ['heroes'], queryFn: () => fetchHeroes(gender, skip, take) })
}
  • If the data will be fetched on the server, is there any sense in it if all the markup will be rendered on the client side anyway?
  • Will there be any SEO benefits?
  • And can I make the whole component rendered on the server? (as I understand no because swiper-js client-side component).
0

There are 0 best solutions below