5

I use react-slick carousel with custom controls. I want to add 'active' class only to element that is changes the slide (by onClick event). But in my case 'active' class toggles for all of them.

export default class ServicesSlider extends React.Component {
    constructor(props) {
        super(props)
        this.changeSlide = this.changeSlide.bind(this)
        this.state = {
            isActive: false
        }
    }
    changeSlide(e) {
        this.setState({
            isActive: !this.state.isActive
        });
        this.slider.slickGoTo(e);
    }
    render() {
        return (
            <div>
                <section className="carousel-controls">
                    <div
                        onClick={() => this.changeSlide(0)}
                        className={this.state.isActive
                        ? 'column' : 'column active'}>Slide one
                    </div>
                    <div
                        onClick={() => this.changeSlide(1)}
                        className={this.state.isActive
                        ? 'column' : 'column active'}>Slide two
                    </div>
                    <div
                        onClick={() => this.changeSlide(2)}
                        className={this.state.isActive
                        ? 'column' : 'column active'}>Slide three
                    </div>
                    <div
                        onClick={() => this.changeSlide(3)}
                        className={this.state.isActive
                        ? 'column' : 'column active'}>Slide four
                    </div>
                </section>
                <Slider ref={c => this.slider = c}>
                    <div className="sliderItem">Slide 1</div>
                    <div className="sliderItem">Slide 2</div>
                    <div className="sliderItem">Slide 3</div>
                    <div className="sliderItem">Slide 4</div>
                </Slider>
            </div>
        )
    }
}

How to properly append class to a specific element in React?

2
  • maintain a state array of active class instead of a single state Commented Aug 4, 2017 at 14:43
  • You are passing an index to changeSlide, but only toggling the active state. The state will therefore be a boolean, true or false, instead of an integer representing the currently active element Commented Aug 4, 2017 at 14:44

4 Answers 4

5

The key is to not keep track of a boolean active, but of the active index. That is, which slide is active: 0, 1, 2, 3, or 4, .... You will need to modify your state to achieve that.

I would also advocate changing the parameter from e to something more descriptive, as e is generally used for events.

If you change your state to

this.state = {
    activeIndex: 0
}

then you can update the active value as such:

changeSlide(index) {
    this.setState({
        activeIndex: index
    });
    this.slider.slickGoTo(index);
}

and then check for active in render:

<div
    onClick={() => this.changeSlide(0)}
    className={this.state.activeIndex !== 0 ? 'column' : 'column active'}>
    Slide one
</div>
Sign up to request clarification or add additional context in comments.

Comments

4

Rather than having an isActive variable, which suggests only a true/false value, why not have a currentActiveSlide variable?

In the constructor you initiate it as null (if you want your App to start with no active slide). And then update it with the index when you click it.

So your changeSlide() function becomes:

changeSlide(idx) {
  // If we click on the already active slide, set "currentActiveSlide" to null.
  // Otherwise, set it to the "idx".
  this.setState({
    currentActiveSlide: idx !== this.state.currentActiveSlide ? idx : null
  });
  this.slider.slickGoTo(idx);
}

I changed your e parameter to idx for clarity. because the former suggests an event. Of course, you would need to update your render as well:

className={this.state.currentActiveSlide === 1 ? 'column' : 'column active'}

(though I think you got the logic reversed here).

Comments

1

You can't have the same state name in all the slides. I suggest creating an array as this.state.isActive, and having each slide be a different index of that array. Then you just change the array index onClick

export default class ServicesSlider extends React.Component {
constructor(props) {
    super(props)
    this.changeSlide = this
        .changeSlide
        .bind(this)
    this.state = {
        isActive: Array(4).fill(false); //new stuff
    }
}
changeSlide(e) {
    const newBool = !this.state.isActive[e]; //new stuff
    var newArray = this.state.isActive;//new stuff
    newArray[e] = (newBool);//new stuff
    this.setState({
        isActive: newArray//new stuff
    });
    this
        .slider
        .slickGoTo(e);
}
render() {
    return (
        <div>
            <section className="carousel-controls">
                <div
                    onClick={() => this.changeSlide(0)}
                    className={this.state.isActive[0]//new stuff
                    ? 'column'
                    : 'column active'}>Slide one
                </div>
                <div
                    onClick={() => this.changeSlide(1)}
                    className={this.state.isActive[1]//new stuff
                    ? 'column'
                    : 'column active'}>Slide two
                </div>
                <div
                    onClick={() => this.changeSlide(2)}
                    className={this.state.isActive[2]//new stuff
                    ? 'column'
                    : 'column active'}>Slide three
                </div>
                <div
                    onClick={() => this.changeSlide(3)}
                    className={this.state.isActive[3]//new stuff
                    ? 'column'
                    : 'column active'}>Slide four
                </div>
            </section>
            <Slider ref={c => this.slider = c}>
                <div className="sliderItem">Slide 1</div>
                <div className="sliderItem">Slide 2</div>
                <div className="sliderItem">Slide 3</div>
                <div className="sliderItem">Slide 4</div>
            </Slider>
        </div>
    )
}
}

Comments

0

Your method should be :

this.setState({
    activeSlide: e
});

Then use:

className={this.state.activeSlide === {x} ? 'column' : 'column active'}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.