Как сделать простой слайдер петли в React? - PullRequest
0 голосов
/ 01 декабря 2019

Извините за мой английский)

Не судите строго, так как я только начал работать с реакцией.

Я сделал простой слайдер на реакции и теперь я хочу сделать его циклическим.

Но я не могу. В моем коде это кажется циклическим, но по какой-то причине пропускает последнюю картинку.

как я могу это исправить?

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>Products</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>
    );
  }
}

Какой лучший способ написать слайдер? Буду рад любой помощи

1 Ответ

0 голосов
/ 03 декабря 2019

Во-первых: есть много способов добиться того, что вы пытаетесь сделать, но я бы так и сделал.

Вместо того, чтобы использовать index для обновления другого состояния, я бы сделал собственноекомпонент для продукта. Внутри этого компонента у вас есть полный доступ к этому состоянию продуктов и реквизитам. Это облегчает работу с правильными данными.

Я также удалил бы следующую / предыдущую логику из состояния и просто сделал бы проверку, должны ли кнопки быть активными при рендеринге.

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
        },
        {
          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
        }
      ]
    }
  }

  handleChange = (arr) => {
    // State updates based on other state should be asynchronous
    // https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
    this.setState((state, props) => {
      const oldArr = [...state.data]
      const arrIndex = oldArr.findIndex(x => x.id === arr.id)
      oldArr[arrIndex] = arr

      return ({
        data: oldArr
      })
    })
  }

  render () {
    return (
      <div className='App'>
        <div>
          <h3>Products</h3>
          <div className='collection'>
            {this.state.data.map((item) => (
              <Product
                item={item}
                key={item.id}
                onChange={this.handleChange}
              />
            ))}
          </div>
        </div>
      </div>
    )
  }
}

class Product extends React.Component {
  handleSlideChange = (e) => {
    const arr = { ...this.props.item }

    if (e.currentTarget.dataset.direction === 'next') {
      arr.currentImageIndex++
    } else {
      arr.currentImageIndex--
    }

    this.props.onChange(arr)
  };

  render () {
    const { item } = this.props
    return (
      <div key={item.id} className='product'>
        <div className='product__image'>
          <div>
            <button
              disabled={item.currentImageIndex <= 0}
              data-direction='prev'
              onClick={this.handleSlideChange}
              className='prev'
            >
            Prev
            </button>
          </div>
          <div>
            <img src={item.images[item.currentImageIndex]} alt='' />
            {item.images.currentImageIndex}
          </div>
          <div>
            <button
              disabled={item.currentImageIndex >= item.images.length - 1}
              data-direction='next'
              onClick={this.handleSlideChange}
              className='next'
            >
            Next
            </button>
          </div>
        </div>
        <div className='product__name'>{item.name} {item.currentImageIndex}</div>
        <div className='product__price'>{item.price}</div>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

    <div id="root"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...