Is there a way with React Slick to have a Carousel inside a Carousel? Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Is there a way with React Slick to have a Carousel inside a Carousel? without wasting too much if your time.

The question is published on by Tutorial Guruji team.

Is there a way with React Slick to have Carousel inside Carousel ?

import Slider from "react-slick";

<Slider
    {...settings}
>
        <div/>
        <div>
            <Slider
                {...settings}
            >
                ...
            </Slider>
       </div>
       <div/>
</Slider>

I tried this kind of code but it completely messed up both carousels.

I don’t need to have swipe, dots or arrow, carousel are fully controlled using slickGoTo.

Answer

I solved my issue, we can have 2 levels multiple nested Sliders with this component :

Carousel.js

import React, {useEffect, useRef, useState} from 'react';
import PropTypes from 'prop-types';
import Slider from 'react-slick';

import 'slick-carousel/slick/slick.css';
import './carousel.scss';

function isInt(value) {
    return !isNaN(value) && (function (x) {
        return (x | 0) === x;
    })(parseFloat(value))
}

function resize() {
    // Trigger resize (IE compatible)
    if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) {
        let event = document.createEvent('UIEvents');
        event.initUIEvent('resize', true, false, window, 0);
        window.dispatchEvent(event);
    } else {
        window.dispatchEvent(new Event('resize'));
    }
}

function Carousel(props) {
    const {children, className, initialSlide, onChange, current, speed, ...rest} = props;

    const sliderRef = useRef(null);

    useEffect(() => {
        initialSlide && setStep(initialSlide)
    }, [initialSlide]);

    useEffect(() => {
        isInt(current) && setStep(current);
    }, [current]);

    const [step, setStep] = useState(initialSlide || 0);
    useEffect(() => {
        step < 0 && setStep(0);
        step > children.length && setStep(children.length);

        sliderRef.current.slickGoTo(step);
        onChange && onChange(step);
    }, [step]);

    const settings = {
        accessibility: false,
        adaptiveHeight: false,
        arrows: false,
        className: className,
        dots: false,
        infinite: false,
        initialSlide: initialSlide || 0,
        slideIndex: initialSlide || 0,
        slidesToScroll: 1,
        slidesToShow: 1,
        speed: speed || 500,
        swipe: false
    };

    const handleBeforeChange = (_, index) => {
        onChange && onChange(index);

        // This setTimeout is needed for adaptive height in nested Carousel
        setTimeout(() => {
            resize();
        }, speed || 500);
    };

    return (
        <Slider
            beforeChange={handleBeforeChange}
            ref={sliderRef}
            {...settings}
            {...rest}
        >
            {React.Children.map(children, (child, index) => (
                    child
                        ? <React.Fragment
                            key={`slide-${index}`}
                        >
                            {React.cloneElement(child, {
                                step: step,
                                setStep: setStep
                            })}
                        </React.Fragment>
                        : () => {
                        }
                )
            )}
        </Slider>
    );
}

Carousel.propTypes = {
    className: PropTypes.string,
    current: PropTypes.number,
    initialSlide: PropTypes.number,
    speed: PropTypes.number,
    onChange: PropTypes.func
};

export default Carousel;

Resize for adaptiveHeight is handled at the beginning and the end of animation.

Use it like this :

<Carousel adaptiveHeight speed={1000} {...props}>
   <Component/>
   <Carousel adaptiveHeight speed={750} {...props}>
       <Component/>
       <Component/>
       <Component/>
       <Component/>
   </Carousel/>
   <Component/>
</Carousel>

/! You cannot have autoFocus prop on <input> inside your Slider (except for step 1)

We are here to answer your question about Is there a way with React Slick to have a Carousel inside a Carousel? - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji