glide
glide copied to clipboard
How could we use glidejs with React ?
Deal all,
I have been struggled with using glide with React, could any of you give an example on how we could use with React ? Thanks.
I agree with this, it would be nice if this is possible
this is a simple implementation using hooks. I don't need handling events, but consider that slider
is a reference to a Glide object, from which you can handle events easily.
import Glide from '@glidejs/glide'
import { useState, useEffect } from 'react'
const Carousel = ({element = 'glide', options, children}) => {
const [slider] = useState(new Glide(`.${element}`, options))
useEffect(() => {
slider.mount()
// subscribe to an event
slider.on('run.before', (event) => {
// ... do something cool here
})
// cleanup when unmounting component
return () => slider.destroy()
}, [])
return (
<div className={element}>
<div className="glide__track" data-glide-el="track">
<ul className="glide__slides">
{children.map((slide, index) => {
return React.cloneElement(slide, {
key: index,
className: `${slide.props.className} glide__slide`
})
})
}
</ul>
</div>
</div>
)
}
and then in component
import Carousel from 'path-to-carousel'
<Carousel element="carousel-class-to-inject" options={{ perView: 3, ... }}
this is a simple implementation using hooks. I don't need handling events, but consider that
slider
is a reference to a Glide object, from which you can handle events easily.
is this the only way? it felt like hacky.
I expanded solution of the @lucari94.
Now, you can set slide position from external Component, when you updated the startAt
props.
I am using this solution:
import React, { Component } from 'react'
import Glide from '@glidejs/glide'
export default class SliderGlide extends Component {
state = { id: null }
componentDidMount = () => {
// Generated random id
this.setState({ id: `glide-${Math.ceil(Math.random() * 100)}` }, this.initializeGlider)
}
initializeGlider = () => {
this.slider = new Glide(`#${this.state.id}`, this.props.options)
this.slider.mount()
}
componentWillReceiveProps = newProps => {
if (this.props.options.startAt !== newProps.options.startAt) {
this.slider.go(`=${newProps.options.startAt}`)
}
}
render = () => (
<div id={this.state.id} style={{ overflowX: 'hidden', userSelect: 'none', maxWidth: '100vw' }}>
<div className="glide__track" data-glide-el="track">
<div className="glide__slides" style={{ display: 'flex' }}>
{this.props.children.map((slide, index) => {
return React.cloneElement(slide, {
key: index,
className: `${slide.props.className} glide__slide`,
})
})}
</div>
</div>
</div>
)
}
SliderGlide.defaultProps = {
options: {},
}
This works if you have only one slider per page. Not per component, per page. I have two sliders with different classes within two different components. Once I add the second component (with the second slider) it runs infinitely and crashes the browser. Here part of my code.
MainSlider.js
import React, { useEffect } from "react";
import Glide from "@glidejs/glide";
import "@glidejs/glide/dist/css/glide.core.min.css";
const Mainslider = ()=>{
const mainGlide = new Glide(".main__glide"); // default options
useEffect(() => {
mainGlide.mount();
return () => mainGlide.destroy();
}, [mainGlide]);
return (
<div className="main__glide">
<div className="glide__track" data-glide-el="track">
<ul className="glide__slides">
<li className="glide__slide">
{/* content 1 */}
</li>
<li className="glide__slide">
{/* content 1 */}
</li>
<li className="glide__slide">
{/* content 2 */}
</li>
<li className="glide__slide">
{/* content 3 */}
</li>
</ul>
</div>
</div>
)
}
The second component is called GallerySlider.js and has similar if not the same code. But none of the two slider mount.
Glide is a vanilla js library and was not created with the focus on use with React, but its quite easy to get it working. This is the way how I would go with a React carousel component that is based on Glide.js.
import Glide from "@glidejs/glide";
import { useImperativeHandle, useEffect, useRef, forwardRef } from "react";
import "@glidejs/glide/dist/css/glide.core.css";
export const Carousel = forwardRef(({ options, children }, ref) => {
const sliderRef = useRef();
useImperativeHandle(ref, () => sliderRef.current);
useEffect(() => {
const slider = new Glide(sliderRef.current, options);
slider.mount();
return () => slider.destroy();
}, [options]);
return (
<div className="glide" ref={sliderRef}>
<div className="glide__track" data-glide-el="track">
<ul className="glide__slides">{children}</ul>
</div>
</div>
);
});
export const Slide = forwardRef(({ children }, ref) => {
return (
<li className="glide__slide" ref={ref}>
{children}
</li>
);
});
Here a complete example on Codesandbox
It's very simple.
import { useRef, useEffect } from "react";
import Glide from "@glidejs/glide";
import "./App.css";
import "./styles.scss";
const sliderConfiguration = {
autoplay: 4000,
};
function App() {
const ref = useRef();
useEffect(() => {
const slider = new Glide(ref.current, sliderConfiguration);
slider.mount();
}, [ref]);
return (
<>
{" "}
<div ref={ref} className="glide">
<div className="glide__track" data-glide-el="track">
<ul className="glide__slides">
<li className="glide__slide">
<div
className="container"
style={{ backgroundColor: "#0033FF" }}
>
text one
</div>
</li>
<li className="glide__slide">
<div
className="container"
style={{ backgroundColor: "#660000" }}
>
text two
</div>
</li>
<li className="glide__slide">
<div
className="container"
style={{ backgroundColor: "#9933CC" }}
>
text three
</div>
</li>
</ul>
</div>
<div className="glide__arrows" data-glide-el="controls">
<button
className="glide__arrow glide__arrow--left"
data-glide-dir="<"
>
prev
</button>
<button
className="glide__arrow glide__arrow--right"
data-glide-dir=">"
>
next
</button>
</div>
<div className="glide__bullets" data-glide-el="controls[nav]">
<button className="glide__bullet" data-glide-dir="=0"></button>
<button className="glide__bullet" data-glide-dir="=1"></button>
<button className="glide__bullet" data-glide-dir="=2"></button>
</div>
</div>
</>
);
}
export default App;
For anyone looking for the typescript version of @jedrzejchalubek solution:
import Glide, { Options } from "@glidejs/glide";
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
export const sliderConfiguration: Partial<Options> = {
type: "carousel",
gap: 20,
perView: 3
};
type CarouselType = {
children: React.ReactNode;
};
export const Carousel = forwardRef(({ children }: CarouselType, ref) => {
const sliderRef = useRef<HTMLDivElement>(null);
useImperativeHandle(ref, () => sliderRef.current);
useEffect(() => {
const slider = new Glide(
sliderRef.current as HTMLElement,
sliderConfiguration,
);
slider.mount();
return () => {
slider.destroy();
};
}, []);
return (
<div className="glide relative md:px-0" ref={sliderRef}>
<div className="glide__track" data-glide-el="track">
<ul className="glide__slides">
{ children }
</ul>
</div>
</div>
);
});
Carousel.displayName = "Carousel";