xoomer
xoomer

Reputation: 321

ReactJS onClick .next() element with same class?

I am new to ReactJS and I was wondering what is the correct way to target next element with same class in react?

<div className="portfolioGallery">
    <img className="portfolioImg activeImg" src="img/1.png"/>
    <img className="portfolioImg" src="img/2.png"/>
    <img className="portfolioImg" src="img/2.png"/>
  <div className="portfolioNext" onClick={this.nextImg.bind(this)}>
     Next image
  </div>
</div>

What would be the correct way that when I click the portfolioNext div I would be able to give the img2 class of activeImg and remove it from the previous element and so on in ReactJS?

Thank You!

constructor() {
    super();
    this.state = {
        default: "portfolioImg activeImg"
    };
}

nextImg() {
    this.setState({
        default: "portfolioImg"
    });
}

Upvotes: 1

Views: 3583

Answers (2)

David Garwin
David Garwin

Reputation: 401

I wouldn't suggest you think of it as siblings finding each other, but instead thing of it as the parent storing an index of the current children, and updating that instead.

this.props (or this.state) would have something like this (pseudocode)

this.props.images => ["img/1.png", "img/2.png", "img/2.png"];

Inside render:

<div className="portfolioGallery">
    {this.props.images.map((image, i ) => active === i ? (<img className="portfolioImg activeImg" src="image" key={i}/>) : (<img className="portfolioImg " src="image" key={i}/>))}
    <button className="portfolioNext" onClick={(e) => this.setState({active: this.state.active + 1}).bind(this)}>Next image</button>
</div>

Of course, accounting for when active >= images.length, but you get the idea

Upvotes: 0

Dan Prince
Dan Prince

Reputation: 30009

That's the kind of imperative technique that you'd generally find in jQuery code, but it doesn't map very well to React's slightly more declarative nature.

Rather than trying to find the next element with a class, use state to maintain a list of those elements alongside an index cursor.

// constructor
this.state = {
  images = ['img/1.png', 'img/2.png', 'img/3.png']
  cursor: 0
};

Then use these bits of data to render your view.

// render
const { images, cursor } = this.state;
return (
  <div>
    {images.map((src, index) => {
      const activeClass = (index === cursor) ? 'activeImg' : '';
      return <img className={`portfolioImg ${activeClass}`} />;
    }}
  </div>
);

To change the active image, use setState to change the cursor property.

// nextImg
const { cursor, images } = this.state;
const nextCursor = cursor % images.length;

this.setState({ cursor: nextCursor });

Upvotes: 3

Related Questions