davidjerleke / embla-carousel

A lightweight carousel library with fluid motion and great swipe precision.
https://www.embla-carousel.com
MIT License
5.87k stars 178 forks source link

Autoplay TypeError Reading InternalEngine Index #270

Closed syedg1 closed 2 years ago

syedg1 commented 2 years ago

Bug is related to

Embla Carousel version

Describe the bug

Expected behavior

Additional context

Capture

davidjerleke commented 2 years ago

Hi @syedg1,

Thanks. This is probably happening because you’re either calling play() before the carousel has been initialized, or after it has been destroyed. It’s possible to solve this by adding an internal condition that only runs play() and all the other methods when the carousel is active, but making it fail silently will make it harder for users to debug their code. Because it won’t tell you that you’re calling a method when it doesn’t do anything.

If you want me to look into this, please create a CodeSandbox with your code.

⚠️ You shouldn’t call autoplay.init() at all because the carousel will do that for you as soon as it initializes. It also handles the destruction automatically when the carousel is destroyed.

Best, David

davidjerleke commented 2 years ago

@syedg1 have you had the chance to read my previous response?

syedg1 commented 2 years ago

@davidjerleke just got around to reading this today. I tried calling autoplay.play() using the onInit and onReInit event listeners to make sure that the carousel is initialized prior to the method call, but the error is still thrown.

I noticed that when I omit the method call, sometimes it autoplays by itself. This is probably because the autoplay.init() function that's automatically run will call the play() function. However, it doesn't always play automatically according to my testing. Sometimes it'll load up, but won't autoplay.

Not sure if it makes a difference, but I'm initializing the carousel with useEmblaCarousel hook as shown below... const autoplay = Autoplay({ delay: 3000, stopOnInteraction: false },(emblaRoot) => emblaRoot.parentElement); const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, align: 0 }, [autoplay]);

syedg1 commented 2 years ago

Update: I came up with a workaround which allows me to autoplay using just the embla API (no plugins required).

const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, align: 0 });
const [counter, setCounter] = useState(0)

//function to initialize autoplay
const onInit = () => {
    console.log("Calling onInit");
    setCounter( prev => prev + 1);
}

//useEffect to initialize event listener
useEffect(() => {
  if(!emblaApi) {
    console.log("Carousel doesn't exist right now");
    return;
  }
  emblaApi.on('init', onInit); 
}, [emblaApi]);

//useEffect to change slides
useEffect(() => {  
  console.log("Counter value: " + counter);
  if (emblaApi) {
    const timer = setTimeout( () => {
      console.log("Scrolling Next");
      emblaApi.scrollNext();
      setCounter( prev => prev + 1);
    }, 3000);
  }
  return () => {
    clearTimeout(timer);
  }
}, [counter]);
davidjerleke commented 2 years ago

Hi again @syedg1,

I still don’t have a clear picture of the problem you’re describing, and I think it’s because you haven’t provided sufficient information. Please read the contributing guidelines. I will try to summarize why this bug report is lacking crucial information:

Additionally, I don’t think the solution you provided solves anything. The Autoplay plugin comes with options that allows for configuring the autoplay behavior in many ways. Also, the code you shared will run when the browser tab is hidden and inactive. This is something that was solved in the latest release 6.1.1.

Please let me know if you’re intending to provide the missing information or not.

Best, David