Open welschmoor opened 10 months ago
Here's a "solution", more of a hackaround which I would not want to implement in production:
We only render 1 slide at first. And 800milliseconds later we increase the number of slides that we loop over to more. Also another 400 milliseconds later we update the slider.
'use client'
import { useKeenSlider } from 'keen-slider/react'
import React, { useEffect, useState } from 'react'
export default function TestPage() {
const [children, setChildren] = useState([null])
const [sliderRef, slider] = useKeenSlider({
loop: true,
slides: {
origin: 'center',
perView: 1,
spacing: 0,
},
})
useEffect(() => {
setTimeout(() => {
setChildren([null, null, null])
}, 800)
setTimeout(() => {
if (slider) {
slider.current?.update()
}
}, 1200)
}, [slider])
return (
<div ref={sliderRef} className="keen-slider" style={{ height: 300 }}>
{children.map((each, index) => {
return (
<div
key={index}
className={
index % 2 === 0
? 'h-full keen-slider__slide number-slide2 bg-red-600'
: 'h-full keen-slider__slide number-slide1 w-full bg-blue-500'
}
>
1
</div>
)
})}
</div>
)
}
Real data can be sliced and the sliceIndex increased from 1 to length of data some milliseconds later: data.slice(0, sliceIndex).map(each => ...
For anyone else who stumbles upon this.. I just solved by only rendering the first image until loaded, once loaded I render the rest and call an update on the instance. Also a bit hacky, but not too bad.
Like this sorta thing:
useEffect(() => {
if (loaded && instanceRef.current) {
instanceRef.current?.update();
}
}, [loaded, instanceRef]);
<div ref={sliderRef} className="keen-slider xl:!hidden">
{/* Always render the first image */}
{renderImage(media[0], 0)}
{/* Conditionally render the remaining images if loaded */}
{loaded && media.slice(1).map((med, i) => renderImage(med, i + 1))}
</div>
const renderImage = (media, i: number) => {
return (
<div
className={`keen-slider__slide `}
key={med.id || image?.id}
>
{image && (
<Image
loading={i === 0 ? 'eager' : 'lazy'}
data={image}
aspectRatio="1"
sizes={
isFirst || isFourth
? '(min-width: 48em) 60vw, 90vw'
: '(min-width: 48em) 30vw, 90vw'
}
/>
)}
</div>
);
};
Hi, I wanted to up this thread. Is there any fix planned ?
I also encounter this bug in all of my nuxt apps if only one slide must be visible at a time.
Thanks
Ребята. Я случайно пофиксил эту проблему добавив точки для пролистывания
`
const setActiveProject = useDefinition(state=>state.setActiveProject);
const [currentSlide, setCurrentSlide] = useState(0)
const [loaded, setLoaded] = useState(false)
const [sliderRef,instanceRef] = useKeenSlider(
{
loop:true,
slides:{
origin:'auto',
perView:1,
},
created(){
setLoaded(true);
}
},
[
slider =>{
slider.on("detailsChanged",()=>{
if(instanceRef.current !== null){
setCurrentSlide(instanceRef.current.track.details.rel)
setActiveProject(instanceRef.current.track.details.rel)
}
})
}
]
)
useEffect(()=>{
instanceRef.current?.update()
},[loaded])
return (
<div className={S.navigation_container}>
<div className={S.slider_container}>
<div ref={sliderRef} style={{height:'100%'}} className={'keen-slider'}>
<div className={`${S.slide} keen-slider__slide`}><Image priority quality={100}alt='Blob' src={Blob} fill/></div>
<div className={`${S.slide} keen-slider__slide`}><Image priority quality={100}alt='Blob' src={Blob} fill/></div>
<div className={`${S.slide} keen-slider__slide`}><Image priority quality={100}alt='Blob' src={Blob} fill/></div>
<div className={`${S.slide} keen-slider__slide`}><Image priority quality={100}alt='Blob' src={Blob} fill/></div>
</div>
</div>
{loaded && instanceRef.current && (
<div className={S.dots}>
{[
...Array(instanceRef.current.track.details.slides.length).keys(),
].map((idx) => {
return (
<button
key={idx}
onClick={() => {
instanceRef.current?.moveToIdx(idx)
}}
className={currentSlide === idx && S.dot__active || S.dot}
></button>
)
})}
</div>
)}
</div>
I've lately built 3 different sliders with keen-slider and all 3 have this bug. Let's say we have a slider with pictures. We visit the page and for a fraction of a second we see all slides at once before they move "off screen" and become a slider.
It's especially well visible on vertical sliders with slides that have different background colors. Horizontal sliders are also affected.
Repo: https://github.com/welschmoor/ksb (yarn install, yarn dev) Video: https://youtu.be/O8LJNZnzfqE
Update: My repo above is not even necessary. I copy pasted the "vertical slider" from the examples page into my next.js project, and the bug is also there
This would be the code:
bug happens in nextjs in old /pages folder as well as in new /app dir. I don't remember seeing this bug last year.