Prev 和 Next 按钮在断点处无法正常工作

Joh*_*cks 8 javascript reactjs react-slick

伙计们,我在react-slick滑块方面遇到了问题。我在滑块上渲染卡片取决于数组长度。我还渲染自定义nextprevious按钮,触发nextprevious功能来更改幻灯片。我也想让这个滑块响应。这意味着它具有根据定义的设置滚动幻灯片的功能。

我为断点定义的设置

992 > 幻灯片滚动 = 3

577 - 991 幻灯片滚动 = 2

0 - 576 幻灯片滚动 = 1

next没有向前滑动时该按钮将被禁用,当没有后向滑动时该previous按钮将被禁用。为了实现此功能,有一个名为 afterChange 的函数可返回幻灯片的当前活动索引。所以我在state. 但我认为我的next按钮逻辑不正确。

我的问题是什么?

  • refresh调整窗口大小时是否有任何方法可以调整滑块,因为幻灯片没有根据breakpoints?

  • 即使前面没有幻灯片,该next按钮也不会在断点处禁用(0 - 576)

  • 当用户更改单张幻灯片然后调整窗口大小以移动到下一张幻灯片时,该Next按钮将变为非活动状态。

我认为问题在于我写在renderArrows函数内部的逻辑。

看到这个

反应灵敏的问题

代码沙盒:查看此

代码:

import React, { useState, useRef } from "react";
import Slider from "react-slick";

// Constant Variables
// Slides scroll behavior on different sizes
const TOTAL_SLIDES = 6;
const DESKTOP_SLIDES_SCROLL = 3;
const TABLET_SLIDES_SCROLL = 2;
const MOBILE_SLIDES_SCROLL = 1;

/**
 * It will return the JSX and register the callbacks for next and previous slide.
 * @param prevCallback {function} - Go back to the previous slide
 * @param nextCallback {function} - Go to the next slide
 * @param state {object} - Holds the state of your slider indexes
 * @param totalSlides {number} - Holds the total number of slides
 * @return {*} - Returns the JSX
 */
const renderArrows = (
  prevCallback,
  nextCallback,
  { currentIndex, slidesToScroll },
  totalSlides
) => {
  const cycleDots =
    currentIndex === 0 ? 1 : Math.ceil(totalSlides / slidesToScroll);
  return (
    <div>
      <button disabled={currentIndex === 0} onClick={prevCallback}>
        Previous
      </button>
      <button disabled={currentIndex > cycleDots} onClick={nextCallback}>
        Next
      </button>
    </div>
  );
};

const App = () => {
  // We just have to keep track of the index by keeping it in the state
  const [state, setState] = useState({ currentIndex: 0, slidesToScroll: 0 });

  // To access underlying DOM object for the slider
  const sliderRef = useRef();

  // Trigger next method to show the next slides
  const next = () => {
    sliderRef.current.slickNext();
  };

  // Trigger previous method to show the previous slides
  const previous = () => {
    sliderRef.current.slickPrev();
  };

  // Slider Settings
  const settings = {
    slidesToShow: 3,
    dots: false,
    draggable: false,
    slidesToScroll: DESKTOP_SLIDES_SCROLL,
    arrows: false,
    speed: 1300,
    autoplay: false,
    centerMode: false,
    infinite: false,
    afterChange: indexOfCurrentSlide => {
      setState({
        currentIndex: indexOfCurrentSlide,
        slidesToScroll: DESKTOP_SLIDES_SCROLL
      });
    },
    responsive: [
      {
        breakpoint: 992,
        settings: {
          slidesToShow: 2,
          slidesToScroll: TABLET_SLIDES_SCROLL,
          afterChange: indexOfCurrentSlide => {
            setState({
              currentIndex: indexOfCurrentSlide,
              slidesToScroll: TABLET_SLIDES_SCROLL
            });
          }
        }
      },
      {
        breakpoint: 576,
        settings: {
          slidesToShow: 1,
          slidesToScroll: MOBILE_SLIDES_SCROLL,
          afterChange: indexOfCurrentSlide => {
            setState({
              currentIndex: indexOfCurrentSlide,
              slidesToScroll: MOBILE_SLIDES_SCROLL
            });
          }
        }
      }
    ]
  };

  return (
    <div className="app">
      <div>
        <h1>Slider Buttons</h1>
        {renderArrows(previous, next, state, TOTAL_SLIDES - 1)}
      </div>

      {/*  Slider */}
      <Slider {...settings} ref={slider => (sliderRef.current = slider)}>
        {[...Array(TOTAL_SLIDES)].map((_, index) => {
          return (
            <div className="card" key={index}>
              <div className="card-img-top">
                <svg
                  className="svg"
                  width="100%"
                  height="225"
                  xmlns="http://www.w3.org/2000/svg"
                  preserveAspectRatio="xMidYMid slice"
                  focusable="false"
                >
                  <rect width="100%" height="100%" fill="#55595c" />
                  <text x="50%" y="50%" fill="#eceeef" dy=".3em">
                    Image {index + 1}
                  </text>
                </svg>
              </div>
              <div className="card-body">
                <p className="card-text">
                  This is a wider card with supporting text below.
                </p>
              </div>
            </div>
          );
        })}
      </Slider>
    </div>
  );
};

export default App;
Run Code Online (Sandbox Code Playgroud)

Nar*_*igo 2

看起来一切都已经正常工作,但Next按钮被禁用了。disabled我认为通过更改条件来检查滑块所在的幻灯片数量应该已经可以工作了。

在提供的代码沙箱中将主体更改renderArrow为此似乎有效:

  const lastElementsIndex = totalSlides - slidesToScroll;
  return (
    <div>
      <button disabled={currentIndex === 0} onClick={prevCallback}>
        Previous
      </button>
      <button disabled={currentIndex > lastElementsIndex} onClick={nextCallback}>
        Next
      </button>
    </div>
  );
Run Code Online (Sandbox Code Playgroud)

由于初始状态与实际值不同步,具体取决于断点,因此可能存在注释中指出的特殊情况。用作onReInit非箭头函数应该可以访问thisSlick 滑块本身的对象。从那里,slidesToScroll可以检索正确的内容:

const settings = {
  // ... other settings ...
  onReInit: function() {
    const slidesToScroll = this.slidesToScroll;
    if (slidesToScroll !== state.slidesToScroll) {
      setState(state => ({ ...state, slidesToScroll }));
    }
  },
  // ... other settings ...
};
Run Code Online (Sandbox Code Playgroud)

在之前的编辑中,我建议使用onInit- 使用onReInit也有在窗口调整大小时进行拍摄的好处。因此,在调整大小时它也应该正确同步状态。

  • 很抱歉我没听懂你的话。这是 Codesandbox 链接 [请参阅此处](https://codesandbox.io/s/react-slick-2-jsk7o-m0e8o) 在此示例中,您可以看到全局变量中的幻灯片总数为“3”,并且在“桌面断点”3张幻灯片已经出现,前面没有幻灯片。所以下一个按钮应该被禁用。 (3认同)