Search code examples
reactjsreact-slick

Hide/Show React-slick arrows


I am using react-slick and I have my own customised arrows. This Slider is NOT an infinite loop and I would like to hide the arrows at the start and end of the loop. So basically at start PrevArrow should be hidden and at the end the NextArrow should be hidden. Which I am trying to set hidden class name depending on state changes. However the class name is not changing although the state is changing correctly. Do you know what's the problem with this code? and how to get it work?

Below is my setting for Slider and the component which renders Slider.

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Slider from 'react-slick';
import Arrow from '../slider/Arrow';


export default class CityCarousel extends Component {
    constructor(props) {
        super(props);

        this.state = {
            displayLeftArrow: true,
            displayRightArrow: true
        };


        this.slidesToShow = 5;
        this.sliderSetting = {
            dots: false,
            arrows: true,
            infinite: false,
            initialSlide: 0,
            slidesToShow: this.slidesToShow,
            slidesToScroll: 1,
            speed: 500,
            rows: 0,
            nextArrow: <Arrow
                    styleClassName={`city-carousel__right ${
                        this.state.displayRightArrow ? '' : 'city-carousel__right--hide'
                    }`}
                    direction="right"
                    clickHandler={this.clickHandler}
                />,
            prevArrow: <Arrow
                    styleClassName={`city-carousel__left ${
                        this.state.displayLeftArrow ? '' : 'city-carousel__left--hide'
                    }`}
                    direction="left"
                    clickHandler={this.clickHandler}
                />,
            afterChange: currentSlide => this.setArrowDisplay(currentSlide)
        };
    }

    clickHandler = direction => {
        if (direction === 'left') {
            this.slider.slickPrev();
        } else if (direction === 'right') {
            this.slider.slickNext();
        }
    };

    setArrowDisplay = currentSlide => {
        const { cityList } = this.props;
        const displayLeftArrow = currentSlide !== 0;
        const displayRightArrow = currentSlide !== cityList.length - this.slidesToShow;

        this.setState({ displayRightArrow, displayLeftArrow });
    };

    render() {
        const { cityList, tours } = this.props;
        return (
            <div>
                <div className="city-selection">
                    <Slider
                        ref={c => this.slider = c }
                        {...this.sliderSetting}
                    >
                        {cityList.length > 0 ? this.renderCityList() : null}
                    </Slider>
                </div>
            </div>
        );
    }
}

Here is also code for Arrow component

import React from 'react';
import PropTypes from 'prop-types';

const Arrow = ({ styleClassName, direction, clickHandler }) => {

    return(
    <div
        className={`slick-arrow--${direction} slider-arrow--${direction} ${styleClassName}`}
        onClick={e => clickHandler(direction)}
    />
)};

Arrow.propTypes = {
    styleClassName: PropTypes.string,
    direction: PropTypes.string,
    clickHandler: PropTypes.func
};

export default Arrow;

Solution

  • It seems react-slick is not re-rendering <Arrow /> with new props, and it's always with first initialized props setting.

    I think the solution is to get <Arrow /> out of slider like this:

        <div className="city-selection">
          <Arrow
            styleClassName={`city-carousel__right ${
              this.state.displayRightArrow ? '' : 'city-carousel__right--hide'
              }`}
            direction="right"
            clickHandler={this.clickHandler}
          />
          <Arrow
            styleClassName={`city-carousel__left ${
              this.state.displayLeftArrow ? '' : 'city-carousel__left--hide'
              }`}
            direction="left"
            clickHandler={this.clickHandler}
          />
          <Slider
            {/* list of items*/}
          </Slider>
        </div>
    

    you can see how it's working in here