Слайдер изображений с React Slick

React slick - отличный компонент карусели для создания слайдера изображений или компонентов пользовательского интерфейса, подобных карусели. Но иногда нам нужен ручной контроль над функциями по умолчанию, которые предоставляет библиотека.

В прошлый раз, когда я работал с библиотекой, я попытался создать слайдер изображений с некоторыми дополнительными функциями, которые React Slick не предоставляет. Мне нужно создать слайдер, в котором я условно покажу каждый навигатор слайдера слева и справа.

Но, к сожалению, в React Slick не было такой возможности, чтобы условно отображать только один стрелочный навигатор.

Сегодня я собираюсь поделиться своим опытом настройки компонента React Slick с помощью настраиваемых навигаторов со стрелками.

Установка

Установка React Slick

yarn add react-slick

Я использую машинописный текст для демонстрации, поэтому мне нужно добавить определение типа.

yarn add @types/react-slick

Подробнее о React Slick

Я также использую Emotion для стилизации компонентов, но это полностью зависит от вас.

использование

Компонент Initial Image Slider

Компонент Sider Arrow

Для простоты я добавлю стили React Slick прямо в Style.css

// Style.css
@import url('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css');
@import url('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css');

Это отобразит простой слайдер изображения.

Щелкните События стрелки ползунка

Теперь нам нужно управлять onClickсобытиями SliderArrow. Функциональность будет переходить к следующему или предыдущему изображению, щелкнув эти SliderArrow.

Если мы перейдем к определению компонента Slider (по Command + Click), который мы используем в компоненте ImageSlider, то мы увидим, что он расширяет компонент React с помощью некоторых дополнительных методов.

Нам нужно получить доступ к методам slickNext и slickPrev.

Для доступа к этим методам мы будем использовать useRef ловушек из react. Мы установим ссылку в компоненте Slider, и тогда мы сможем получить доступ ко всем общедоступным свойствам и методам из компонента Slider, используя эту ссылку.

const sliderRef = useRef<Slider>(null);
..........
return (
     <SliderWrapper>
       <SliderArrow type="prev" onClick={() => sliderRef.current.slickPrev()} />}
.................
       <SliderArrow type="next" onClick={() => sliderRef.current.slickNext()} />}
     </SliderWrapper>
);

Теперь, если вы нажмете на ползунок со стрелкой, вы сможете перемещаться по изображениям с помощью этих двух кнопок.

Расширенные возможности

Пришло время сделать слайдер более интеллектуальным.

Если мы находимся в начале ползунка, тогда нет смысла показывать предыдущую стрелку, а если мы находимся в конце ползунка, мы также не должны показывать следующую стрелку.

Чтобы контролировать видимость, нам нужно знать текущее положение слайда. Мы можем получить это с помощью опции afterChange из объекта настроек слайдера.

const settings: Settings = {
    .......,
    afterChange: (currentSlide: number) => handleChangeSlide(currentSlide)
}

Мы также объявим два состояния для управления видимостью кнопок со стрелками. Еще одно состояние, чтобы установить максимальное количество слайдов для показа.

const [showRightArrow, setShowRightArrow] = useState<boolean>(false);
const [showLeftArrow, setShowLeftArrow] = useState<boolean>(false);
const [maxNumberOfCardsToShow, setMaxNumberOfCardsToShow] = useState<number>(0);

Обработчик слайдов изменений

const handleChangeSlide = (currentSlide: number) => {
   const leftArrowVisible = currentSlide !== 0;
   const rightArrowVisible = currentSlide <= data.length - maxNumberOfCardsToShow;
setShowLeftArrow(leftArrowVisible);
   setShowRightArrow(rightArrowVisible);
};

Приведенный выше код обработчика будет выполняться после каждого изменения слайда.

Теперь условно отрендерим кнопки со стрелками.

{showLeftArrow && ( <SliderArrow type="prev" onClick={() => sliderRef.current.slickPrev()} />)}
........
{showRightArrow && ( <SliderArrow type="next" onClick={() => sliderRef.current.slickNext()} />)}

Теперь, когда компонент визуализируется первым, мы должны проверить максимальное количество изображений, которые мы можем показать в одном кадре, а также мы должны проверить, покажем ли мы стрелку вправо или нет.

Поэтому мы установим еще один div referenceSliderWrapper, чтобы знать ширину оболочки.

const sliderWrapperRef = useRef<HTMLDivElement>(null);
...
<SliderWrapper ref={sliderWrapperRef}>

Все вычисления будем проводить внутри хука useEffect.

useEffect(() => {
  const wrapperWidth = sliderWrapperRef.current.clientWidth || 0;
  
  const maxNumberOfCards = Math.ceil(wrapperWidth / EACH_SLIDE_WIDTH);
  
  setMaxNumberOfCardsToShow(maxNumberOfCards);
  setShowRightArrow(data.length > maxNumberOfCards);
}, []);

Я объявил EACH_SLIDE_WIDTH как константу в верхней части компонента. Вы также можете получить это значение как реквизит.

const EACH_SLIDE_WIDTH = 176;

Это все! Теперь у вас есть полнофункциональный слайдер изображений со всеми элементами управления под рукой.

Я сделал еще несколько улучшений рефакторинга и стиля. Вот ссылка на полный код.