@timonck

Как сделать слайдер зацикленным?

Я сделал простой слайдер.
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [
        {
          id: 1,
          name: "Product 1",
          price: 50,
          q: 0,
          category: "Sporting Goods",
          images: [
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property04.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg"
          ],
          currentImageIndex: 0,
          isCycleMode: false,
          cantGoPrev: false,
          cantGoNext: true
        },
        {
          id: 2,
          name: "Product 2",
          price: 70,
          q: 0,
          category: "Sporting Goods",
          images: [
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property04.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg",
            "https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg"
          ],
          currentImageIndex: 0,
          isCycleMode: false,
          cantGoPrev: false,
          cantGoNext: true
        }
      ]
    };
  }

  nextSlideHandler = (e, item, index ) => {
    let arr = [...this.state.data];
    let newIndex = this.state.data[index].currentImageIndex;
    if (e.currentTarget.dataset.direction === "next") {
      if (newIndex < this.state.data[index].images.length - 1) {
        newIndex = this.state.data[index].currentImageIndex + 1;
        arr[index].cantGoPrev = true;

        this.setState({data:arr})
      }

      if (newIndex === this.state.data[index].images.length - 1) {
        newIndex = 0;
        arr[index].cantGoNext = true;

        this.setState({data:arr})
      }
    } else {
      if (newIndex > 0) {
        newIndex = this.state.data[index].currentImageIndex - 1;
        arr[index].cantGoNext = true;
        this.setState({data:arr})
      }

      if (newIndex === 0) {
        arr[index].cantGoPrev = false;

        this.setState({data:arr})
      }
    }
    arr[index].currentImageIndex = newIndex;
    this.setState({ data:arr });
  }

  render() {
    return (
      <div className="App">
        <div>
          <h3>Товары</h3>
          <div className="collection">
            {this.state.data.map((item, index) => (
              <div key={item.id} className="product">
                <div className="product__image">
                  <div>
                    
                    <button
                      disabled={!item.cantGoPrev}
                      data-direction="prev"
                      onClick={(e)=> this.nextSlideHandler(e,item, index)}
                      className="prev"
                    >
                      prev
                    </button>
                  </div>
                  <div>
                    <img
                      src={item.images[item.currentImageIndex]}
                      alt=""
                    />
                    {item.images.currentImageIndex}
                  </div>
                  <div>
                    <button
                      disabled={!item.cantGoNext}
                      data-direction="next"
                      onClick={(e)=> this.nextSlideHandler(e, item, index)}
                      className="next"
                    >
                      next
                    </button>
                  </div>
                </div>
                <div className="product__name">{item.name}</div>
                <div className="product__price">{item.price}грн</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Хочу сделать его зацикленным, но почему-то не получается. Он у меня пропускает последнюю картинку перед тем, как перейти к первой. Как это исправить?
  • Вопрос задан
  • 154 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
Не надо закидывать картинки в стейт, пусть компонент получает их через props.

Добавите в стейт свойство, содержащее индекс отображаемой картинки, делайте ему +/- 1, в зависимости от нажатой кнопки, выход за границы массива поправляйте через взятие остатка от деления на его длину:

state = {
  active: 0,
}

nextSlideHandler = ({ target: { dataset: { step } } }) => {
  const len = this.props.images.length;

  this.setState(({ active }) => ({
    active: (active + len + +step) % len,
  }));
}


<button data-step="-1" onClick={this.nextSlideHandler} className="prev">prev</button>
<button data-step="+1" onClick={this.nextSlideHandler} className="next">next</button>
<img src={this.props.images[this.state.active]} />

https://jsfiddle.net/e7vzm9kq/
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@f_ban
nextSlideHandler = (e, item, index ) => {
  let arr = [...this.state.data];
  const {direction} = e.currentTarget.dataset;
  const {currentImageIndex,
         images} = this.state.data[index];
  const newIndex = direction === 'next'
                  ? (currentImageIndex+1) % (images.length-1)
                  : ((currentImageIndex || images.length)-1) % (images.length-1);
  arr[index].cantGoNext = true;
  arr[index].cantGoPrev = newIndex !== 0;
  arr[index].currentImageIndex = newIndex;

  this.setState({ data:arr });
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы