Closed flayks closed 4 years ago
Just for the context, this is kind of what I'm trying to achieve, with code based on this answer, but it doesn't really seem to work when resizing to a >768 screen size from mobile (it should destroy but the carousel is still "active" and has inline styles applied)
import React, { useRef, useEffect, useState } from 'react'
import EmblaCarousel from 'embla-carousel'
import { debounce } from '../utils/functions'
const Carousel = ({ children, settingsProps = '' }) => {
const carousel = useRef(null)
let embla = null
// Settings
const settings = {
loop: true,
...settingsProps
}
// Check for Embla
const checkEmbla = () => {
if (window.innerWidth < 768) {
if (embla === null) {
embla = EmblaCarousel(carousel.current, settings)
}
} else {
if (embla != null) {
console.log('destroy')
embla.destroy()
embla = null
}
}
}
useEffect(() => {
checkEmbla(embla)
window.addEventListener('resize', () => debounce(checkEmbla(), 100))
}, [embla])
return (
<div className="carousel" ref={carousel}>
<div className="carousel__items">
{children}
</div>
</div>
)
}
export default Carousel
Hello Félix (@flayks),
Thank you for your question. I think the code in this old issue you mention is probably outdated. A lot has changed with the React implementation of Embla Carousel since then.
I took some time to create a CodeSandbox that implements what you want to achieve. Here's the CodeSandbox with its related code if you want to check it out:
const EmblaCarousel = ({ children }) => {
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: false });
const [emblaIsActive, setEmblaIsActive] = useState(false);
const initEmblaBelow768px = useCallback(() => {
const isActive = window.innerWidth < 768;
setEmblaIsActive(isActive);
}, [setEmblaIsActive]);
useEffect(() => {
initEmblaBelow768px();
window.addEventListener("resize", initEmblaBelow768px);
return () => window.removeEventListener("resize", initEmblaBelow768px);
}, [initEmblaBelow768px]);
return (
<div className="embla">
<div className="embla__viewport" ref={emblaIsActive ? emblaRef : null}>
<div className="embla__container">
{/* ...slides */ }
</div>
</div>
</div>
);
};
null
, and if there's an activated instance of Embla it will destroy it automatically.null
when the screen width is >= 768.Let me know if it helps! David
Thank you so much @davidcetinkaya for your time and answer! That sounds very good. I'll have a look tomorrow and let you know.
@davidcetinkaya I tried your example and it works… partially, haha. Even on your CodeSandbox, it seems that coming from a small screen (<768, where the carousel is enabled), to the Desktop, the carousel is not really destroyed and we can still drag slides. The behavior should be that when starting on mobile, it should dynamically destroy and reinit the carousel.
@flayks that’s strange. I can’t drag it and the scenario you mention works for me. Which link did you click on?
Try this link: https://isr3u.csb.app/
This exact one! Here is a video to show more context: https://streamable.com/8zzx85
So strange. Thanks for the video @flayks. I’ll take a look at it and will let you know when I have something.
Hello again Félix (@flayks),
So I found why this is happening. Embla will re-initialize on the resize event internally, and this resize event is debounced with 500 milliseconds. This is my understanding of the issue:
null
Embla destroys itself.To solve this I will ship a patch fix as soon as possible. I'll have to make sure the internal re-initialize function doesn't run when the carousel has been destroyed. Nice catch 🙂!
Kindly, David
@davidcetinkaya Oh wow, good work on finding that David! I kind of saw when trying the resizing method that it was debounced, but I didn't know that it would affect the destroy method as well. Thanks for your digging. Other than that, the library is on point 👌
@davidcetinkaya hella fast! Thanks for fixing that issue, it's gonna help lots on my current project 💥
Hello Félix (@flayks),
Release 4.0.2 comes with a fix for this issue. Please let me know if it's working as intended.
Best, David
@flayks so this solves the issue right 🙂?
@davidcetinkaya absolutely! Works like a charm now. Thanks again!
I’m glad to hear that @flayks. Thank you for opening this issue and making Embla Carousel better 👍🏻.
Best, David
I'm trying to use Embla (which is fantastic btw, great job) only on mobile, so sort of disabling it on desktop when it's been enabled on mobile (i.e. window resize or orientation change).
So for instance:
Flickity has this cool feature where it tracks if a CSS
after
element has a certain content, then enables or disables it with CSS breakpoints. But it's also 51kb of JS, so Embla is def more optimized and lightweight!Is there any way to have a similar kind of behavior with Embla without having to listen to a window resize event and
embla.destroy()
(which doesn't seem to completely destroy my instances btw) +embla.reInit(options)
everytime? Or am I missing something?