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

Using breakpoints option in Next JS causes Hydration error #5784

Closed
Sakkhor909 opened this issue Jun 8, 2022 Discussed in #5776 · 25 comments
Closed

Using breakpoints option in Next JS causes Hydration error #5784

Sakkhor909 opened this issue Jun 8, 2022 Discussed in #5776 · 25 comments

Comments

@Sakkhor909
Copy link

Sakkhor909 commented Jun 8, 2022

Discussed in #5776

Originally posted by Sakkhor909 June 7, 2022
First of all, thank you for this amazing library.

Everything works fine until I use breakpoints

import { Swiper, SwiperSlide } from "swiper/react";
import Image from "next/image";

 <Swiper

        slidesPerView={1}

        breakpoints={{
          1024: {
            slidesPerView: 3,
          },
        }}
 
      >
        {Data.images.map((imgSrc, index) => {
          return (
            <SwiperSlide>
              <Image src={imgSrc} alt={Data.name + index} layout="fill" />
            </SwiperSlide>
          );
        })}
      </Swiper>

The error is shown on the next js page

Error: Hydration failed because the initial UI does not match what was rendered on the server.
@AbdushukurRasulov
Copy link

Than same issue with me also

@Jared0430
Copy link

Same here

@iampawan31
Copy link

I am also facing the same issue.

@ssandlan
Copy link

Same issue

@iampawan31
Copy link

iampawan31 commented Jun 16, 2022

Using slidesPerView="auto" fixed the issue for me.

Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

@laurenskling
Copy link

This actually makes sense. Your static build created the HTML without a screensize, so the default settings are run. When your JS runs for the first time, it will consider breakpoints, thus creating a mismatch in HTML elements.

@Sakkhor909
Copy link
Author

Using slidesPerView="auto" fixed the issue for me.

Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

Thank you for the solution. It works.

@jordanlambrecht
Copy link

Using slidesPerView="auto" fixed the issue for me.
Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

Thank you for the solution. It works.

I want to have a bit of the next slide peaking on the screen, so slidesPerView=auto won't work for me- any other ideas or possible fixes you came up with?

@Sakkhor909
Copy link
Author

At the moment, No

@Sakkhor909 Sakkhor909 reopened this Jul 12, 2022
@AbdushukurRasulov
Copy link

<div className="relative w-full lg:mx-auto lg:max-w-7xl">
          <Swiper
            slidesPerView={3}
            spaceBetween={20}
            breakpoints={{
              768: {
                slidesPerView: 4,
                spaceBetween: 20,
              },
              1024: {
                slidesPerView: 5,
                spaceBetween: 10,
              },
              1280: {
                slidesPerView: 6,
              },
              1440: {
                slidesPerView: 7,
              },
            }}
          >
            {[...Array(7).keys()].map((item) => (
              <SwiperSlide key={item}>
                Slide {item}
               </SwiperSlide>
            ))}
          </Swiper>
        </div>

This is my solution. I have used Tailwind CSS, and wrapped Swiper with one more div, and gave width: 100%.
it works ok

@alimasha-design
Copy link

Using slidesPerView="auto" fixed the issue for me.

Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

Great Solution.
Many thanks for giving your valuable time to fix it.

@laurenskling
Copy link

Just want to clarify here, slidesPerView="auto" is not a fix, it's a workaround.

@moinulmoin
Copy link

slidesPerView="auto" also resolved my issue. thanks @iampawan31

@vicasas
Copy link

vicasas commented Oct 10, 2022

If you decide to use slidesPerView="auto" you have to take into account that you have to control the CLS (Web Vitals) since doing this causes the images to move, in the first render they will be loaded automatically while in the next one it will exist a design change.

@MuharremGonel
Copy link

Using slidesPerView="auto" fixed the issue for me.

Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

Thank you for the solution. It works.

@sandrinjoy
Copy link

Is anyone still getting hydration error even after using slidesperview ="auto" ?

<Swiper
          spaceBetween={50}
          slidesPerView="auto"
          loopedSlides={3}
          pagination={{
            el: ".my-custom-pagination-div",
            clickable: true,
            renderBullet: (index, className) => {
              return '<span class="' + className + '">' + "</span>";
            },
          }}
          navigation={true}
          loop={true}
          centeredSlides={true}
          breakpoints={{
            992: {
              slidesPerView: 2,
            },
          }}
          onSlideChange={(swiperCore) => {
            const { activeIndex, snapIndex, previousIndex, realIndex } =
              swiperCore;
            setActiveApp(realIndex);
          }}

          // left and right carousels should be half
          // width of the slide
        >
          {data.map((item, index) => {
            return (
              <SwiperSlide key={index}>
                <DataCard
                  visits={visits}
                  item={item}
                  active={activeData === index}
                />
              </SwiperSlide>
            );
          })}

          {isDesktop && (
            <>
              <PrevOverlay />
              <NextOverlay />
            </>
          )}
        </Swiper>

@jakeprins
Copy link

Is anyone still getting hydration error even after using slidesperview ="auto" ?

<Swiper
          spaceBetween={50}
          slidesPerView="auto"
          loopedSlides={3}
          pagination={{
            el: ".my-custom-pagination-div",
            clickable: true,
            renderBullet: (index, className) => {
              return '<span class="' + className + '">' + "</span>";
            },
          }}
          navigation={true}
          loop={true}
          centeredSlides={true}
          breakpoints={{
            992: {
              slidesPerView: 2,
            },
          }}
          onSlideChange={(swiperCore) => {
            const { activeIndex, snapIndex, previousIndex, realIndex } =
              swiperCore;
            setActiveApp(realIndex);
          }}

          // left and right carousels should be half
          // width of the slide
        >
          {data.map((item, index) => {
            return (
              <SwiperSlide key={index}>
                <DataCard
                  visits={visits}
                  item={item}
                  active={activeData === index}
                />
              </SwiperSlide>
            );
          })}

          {isDesktop && (
            <>
              <PrevOverlay />
              <NextOverlay />
            </>
          )}
        </Swiper>

Yes

@kentakunkentakun
Copy link

Is anyone still getting hydration error even after using slidesperview ="auto" ?

<Swiper
          spaceBetween={50}
          slidesPerView="auto"
          loopedSlides={3}
          pagination={{
            el: ".my-custom-pagination-div",
            clickable: true,
            renderBullet: (index, className) => {
              return '<span class="' + className + '">' + "</span>";
            },
          }}
          navigation={true}
          loop={true}
          centeredSlides={true}
          breakpoints={{
            992: {
              slidesPerView: 2,
            },
          }}
          onSlideChange={(swiperCore) => {
            const { activeIndex, snapIndex, previousIndex, realIndex } =
              swiperCore;
            setActiveApp(realIndex);
          }}

          // left and right carousels should be half
          // width of the slide
        >
          {data.map((item, index) => {
            return (
              <SwiperSlide key={index}>
                <DataCard
                  visits={visits}
                  item={item}
                  active={activeData === index}
                />
              </SwiperSlide>
            );
          })}

          {isDesktop && (
            <>
              <PrevOverlay />
              <NextOverlay />
            </>
          )}
        </Swiper>

I had a similar situation, but solved it by limiting Swiper calls to client-side. It may be a bit of a messy solution....

const [isClient, setIsClient] = useState(false)
const createSwiper = () => {
  if (isClient) {
    return <SlideShowContainer />
  } else {
    <></>
  }
}
useEffect(() => {
  setIsClient(true)
}, [])

// use createSwiper()
const SwiperContainer = () => {
 return {createSwiper()}
}

// Define Swiper
const SlideShowContainer = () => {
 return (
  <Swiper
   .....>
  </Swiper>
}

@Helius01
Copy link

Helius01 commented Nov 13, 2022

Using slidesPerView="auto" fixed the issue for me.

Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

it does not worked for me .
the breakepoints section working with window object and its not accessible on Hydration .
so is there any solution?

@Helius01
Copy link

I don't know is it dirty or not? but i fixed it by the code :

  const [customSwiperOptions, setCustomSwiperOptions] = useState<SwiperOptions>();

  useEffect(() => {
    const options: SwiperOptions = {
      breakpoints: {

        320: {
          slidesPerView: 1,
        },
        640: {
          slidesPerView: 2,
        },
        768: {
          slidesPerView: 3,
        },
        1024: {
          slidesPerView: 4,
        },
        1280: {
          slidesPerView: 5,
        },
        1536: {
          slidesPerView: 6
        }
      }
    }
    setCustomSwiperOptions(options);
  }, [])

 {
          customSwiperOptions &&
          <Swiper modules={[Navigation, Pagination, Scrollbar, A11y]}
            spaceBetween={20}
            navigation
            breakpoints={customSwiperOptions.breakpoints}
            pagination={{ clickable: true }}
            scrollbar={{ draggable: true }}>
            {
              myItems.map((x) => {
                return <SwiperSlide key={x.id} className='p-2'> <Item data={x}></Item></SwiperSlide>
              })
            }
          </Swiper>
}

@sandrinjoy
Copy link

sandrinjoy commented Nov 13, 2022

Even if we keep swiper client side, isn't it causing a huge CLS ?

@pieeee
Copy link

pieeee commented Nov 22, 2022

Using slidesPerView="auto" fixed the issue for me.

Sample Code for reference

<Swiper
        spaceBetween={10}
        slidesPerView="auto"
        breakpoints={{
          320: {
            slidesPerView: 1,
            spaceBetween: 30,
          },
          640: {
            slidesPerView: 1,
            spaceBetween: 10,
          },
          768: {
            slidesPerView: 2,
            spaceBetween: 20,
          },
          1024: {
            slidesPerView: 3,
            spaceBetween: 30,
          },
        }}
      >
              <SwiperSlide>Slide one</SwiperSlide>
      </Swiper>

That works, Thanks!!

@ajmaurya99
Copy link

Thanks it worked for me. :)

@kaidezen
Copy link

kaidezen commented Dec 24, 2022

I don't know is it dirty or not? but i fixed it by the code :

  const [customSwiperOptions, setCustomSwiperOptions] = useState<SwiperOptions>();

  useEffect(() => {
    const options: SwiperOptions = {
      breakpoints: {

        320: {
          slidesPerView: 1,
        },
        640: {
          slidesPerView: 2,
        },
        768: {
          slidesPerView: 3,
        },
        1024: {
          slidesPerView: 4,
        },
        1280: {
          slidesPerView: 5,
        },
        1536: {
          slidesPerView: 6
        }
      }
    }
    setCustomSwiperOptions(options);
  }, [])

 {
          customSwiperOptions &&
          <Swiper modules={[Navigation, Pagination, Scrollbar, A11y]}
            spaceBetween={20}
            navigation
            breakpoints={customSwiperOptions.breakpoints}
            pagination={{ clickable: true }}
            scrollbar={{ draggable: true }}>
            {
              myItems.map((x) => {
                return <SwiperSlide key={x.id} className='p-2'> <Item data={x}></Item></SwiperSlide>
              })
            }
          </Swiper>
}

Thank you for this, I feel this is the best solution on this thread!

I made some small simplifications:

`
const [customSwiperOptions, setCustomSwiperOptions] = useState(null);

useEffect(() => {
const options = {
640: {
slidesPerView: 2,
spaceBetween: 20,
},
768: {
slidesPerView: 2,
spaceBetween: 20,
},
1024: {
slidesPerView: 3,
spaceBetween: 20,
},
1200: {
slidesPerView: 4,
spaceBetween: 20,
},
}
setCustomSwiperOptions(options);
}, [])

const testimonialCarousel = {
slidesPerView: 1,
spaceBetween: 20,
loop: true,
speed: 1000,
centeredSlides: true,
autoHeight: true,
modules: [Autoplay],
autoplay: {
waitForTransition: false,
delay: 4000,
},
breakpoints: customSwiperOptions
};

{customSwiperOptions && <Swiper {...testimonialCarousel}
    >
      {TESTIMONIALS_DATA.map((item, index) => (
        <SwiperSlide key={index}>
          {item.map(({ image, text, name, username }, _index) => (
            <TestimonialsCard
              image={image}
              text={text}
              name={name}
              key={_index}
              username={username}
              sx={styles.testimonialsCard}
            />
          ))}
        </SwiperSlide>
      ))}
    </Swiper>}`

@bandesha101
Copy link

this is nice

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