react-slick icon indicating copy to clipboard operation
react-slick copied to clipboard

slickGoTo inside useEffect doesn't work.

Open adammo94 opened this issue 3 years ago • 20 comments

so I have following problem, I want my slider to go back to slide 6 after if anyone would try to swipe further. However it doesn't work. UseEffect is being triggered, IF condition is being met, but the function won't run. If I put the same function call inside JSX like first snippet below it works how it should:

<button onClick={() => sliderRef.current.slickGoTo(5)} >go to slide 6</button>

This is my code:

const [activeSlide, setActiveSlide] = useState(0)
const sliderRef = useRef(null)
  const settings = {
    variableWidth: true,
    speed: 500,
    pauseOnHover: false,
    swipeToSlide: false,
    focusOnSelect: false,
    infinite: false,
    slidesToScroll: 1,
    arrows: false,
    beforeChange: (current, next) => setActiveSlide(next)
  }
useEffect(() => {
    if (window.innerWidth > 1100 && activeSlide > 5) {
      sliderRef.current.slickGoTo(5)
    }
  }, [activeSlide])
<Slider {...settings} className={sliderClass} ref={sliderRef}>

adammo94 avatar May 21 '21 15:05 adammo94

@adammo94 If you do sliderRef.current.slider.slickGoTo(5), it should work. Apparently the ref is given the whole Carousel instance, not just the slider.

devdpontes avatar Jun 07 '21 12:06 devdpontes

Same issue here

faridsaud avatar Jun 07 '21 23:06 faridsaud

@adammo94 If you do sliderRef.current.slider.slickGoTo(5), it should work. Apparently the ref is given the whole Carousel instance, not just the slider.

This gives me undefined

adammo94 avatar Jun 08 '21 08:06 adammo94

@adammo94 what happens if you console.log sliderRef.current inside the effect?

What if you try:

useEffect(() => { if (window.innerWidth > 1100 && activeSlide > 5) { sliderRef.current.slickGoTo(5) } }, [activeSlide, sliderRef.current])

clearyandzap avatar Jun 30 '21 10:06 clearyandzap

any update on this issue? having the same problem.

McSam94 avatar Sep 27 '21 13:09 McSam94

The following keeps me working normally

 const sliderRef = useRef(null);

 <Slider  ref={sliderRef} />
 
 sliderRef.current?.slickNext?.()

x1aodingdang avatar Oct 15 '21 04:10 x1aodingdang

@adammo94

You've forgot to put in sliderRef.current into dependency array of the useEffect:

useEffect(() => {
    if (window.innerWidth > 1100 && activeSlide > 5) {
      sliderRef.current.slickGoTo(5)
    }
  }, [activeSlide, sliderRef.current])

scratch that, refs do not affect rendering, so this will not do anything

MonstraG avatar Nov 25 '21 12:11 MonstraG

It looks like sliderRef.current returns the DOM element instead of the slick instance. Any updates on this?

diego06884 avatar Feb 16 '22 17:02 diego06884

same problem here, tried above ideas but dont work. Any idea for a workaround?

alex254 avatar Apr 06 '22 14:04 alex254

cant figure out why its not working, please help

alex254 avatar Apr 07 '22 11:04 alex254

@alex254 Have you resolved this issue?

upd. check this thread, it helped me #2264

pbl6asoad avatar Apr 18 '22 09:04 pbl6asoad

@pbl6asoad nope, tried the waitForAnimate, issue persists.

here is my code:

function ProductImage({
  images, product, influencer, selectedVariant, hideDescription = false,
}: ProductImageProps) {
  const [, setState] = useState(false);
  const [index, setIndex] = useState(0);
  const sliderImageRef = useRef(null);
  const sliderNavRef = useRef(null);

  const { t } = useTranslation();

  useEffect(() => {
    setState(true);
    // on a new variant selection we want the image to slide to the variant image. However there is a bug in slickGoTo which is not working.
    // if (selectedVariant && sliderImageRef) {
    //   sliderImageRef.current.slickGoTo(1);
    // }
  }, [selectedVariant, sliderImageRef]);

  const currentProduct = Array.isArray(product) ? product[index] : product;

  const CarouselComponent = (
    <>
      <SliderContainer>
        <NavigationSlider
          asNavFor={sliderImageRef && sliderImageRef.current}
          // eslint-disable-next-line no-return-assign
          ref={sliderNavRef}
          slidesToShow={3}
          slidesToScroll={1}
          focusOnSelect
          vertical
          verticalSwiping
          arrows={false}
        >
          {
            images?.map((image) => <NavigationImage key={image.src} src={image.src} />)
          }
        </NavigationSlider>
        <ImageSlider
          asNavFor={sliderNavRef && sliderNavRef.current}
          // eslint-disable-next-line no-return-assign
          ref={sliderImageRef}
          slidesToShow={1}
          slidesToScroll={1}
          swipeToSlide
          dots
          arrows={false}
          afterChange={setIndex}
          appendDots={(dots) => (
            <DotsContainer>
              <ul> {dots} </ul>
              <TabletAvatar product={currentProduct} influencer={influencer} />
            </DotsContainer>
          )}
        >
          {
            images?.map((image) => (
              <InnerImageZoom
                key={image.src}
                className="customImageZoom"
                src={image.src}
                imgAttributes={{
                  src: image.src,
                  title: image.alt,
                  alt: image.alt,
                }}
                zoomScale={1.5}
                fullscreenOnMobile
              />
            ))
          }
        </ImageSlider>
      </SliderContainer>
    </>
  );

  return (
    <div
      data-cy="carousel"
    >{CarouselComponent}
    </div>
  );
}

export default ProductImage;

and an impression:

image

any suggestion on how to solve this?

alex254 avatar Apr 26 '22 09:04 alex254

@akiran @devdpontes : Any updates on this? For me its working on 2nd click. But not the first!

aniruddhashevle avatar Nov 17 '22 10:11 aniruddhashevle

@akiran @devdpontes : Any updates on this? For me its working on 2nd click. But not the first!

@aniruddhashevle Sorry for the late reply but we've decided to migrate to a smaller alternative, so unfortunately I can't give more input on this at the moment. I can try to checkout the previous code at some point and see if I can help figure out what could be happening.

devdpontes avatar Dec 05 '22 11:12 devdpontes

Any updates or workarounds on this issue? @akiran @devdpontes

ankumar3 avatar Apr 29 '23 14:04 ankumar3

@ankumar3 Not sure on the cause. But for me, I have found that useRef doesn't work and I needed to create a state reference. So, instead of:

const sliderRef = useRef(null);
...
<Slider ref={ sliderRef }>

I had to use the following:

const [ slickSlider, setSlickSlider ] = useState(null);
...
<Slider ref={ slider => setSlickSlider( slider ) }>

I found this out from this example.

jaredparker avatar May 02 '23 11:05 jaredparker

Awesome, thanks for sharing @jaredparker

In my case, I needed to open a particular slide on Carousel Init only so I used the Slider onInit like this: const onInit = () => {setInitState(true)} ... <Slider ref={ sliderRef } onInit={onInit}>

And then used the useEffect: useEffect(() => { sliderRef.current?.slickGoTo(index) }, [initState])

ankumar3 avatar May 04 '23 05:05 ankumar3

What helped me: const sliderRef = useRef(null); useEffect(() => sliderRef.current?.innerSlider?.changeSlide({ message: 'index', index: 0 }, true), [])

Got that from reading react-slick code

boshka0 avatar Jun 27 '23 12:06 boshka0

Hi everyone! Just add second argument. I think it is animation bag, and need to turn off it. For me worked sliderRef.current.slickGoTo(selectedIndex, true) I found this out from API https://react-slick.neostack.com/docs/api

TimaRadjabov avatar Dec 22 '23 07:12 TimaRadjabov

Hey guys, any updates on this issue? None of the solutions worked for me. Is it planned to be fixed?

VMLuca avatar Mar 15 '24 12:03 VMLuca