reactjstypescriptionic-frameworkion-slides

ion-slides - dynamic amount of slides


I'm working with the IonSlides component and I'm running into following issue.
I have an array of dates and have to create a IonSlide component for each of these dates. The user has the possibility to rearrange the start and end date. If the length of the dates array differs from the previous length, the layout breaks.
I managed it to manually call the Swiper API, and with this workaround the slides correctly appear.

Currently a colleague on MacOS is running into following error message, which I don't get on Windows (same Ionic and Node version):

Unhandled Rejection (TypeError): Cannot read property 'length' of undefined
Swiper.removeAllSlides
node_modules/@ionic/core/dist/esm-es5/swiper.bundle-3fe6462e.js:2415
workaround
src/components/Slides/Slides.tsx:31
  28 | const workaround = async() => {
  29 |   // https://swiperjs.com/api/
  30 |   let swiper = await this.slidesRef.current.getSwiper();
> 31 |   swiper.removeAllSlides();
     | ^  32 |   swiper.appendSlide(this.props.slides.map((slide, i) => {
  33 |     return ReactDOMServer.renderToString(<Slide slide={slide} key={i} />); // redundanter code
  34 |   }));

Furthermore after calling swiper.removeAllSlides(); and rebuilding the slides, the scrollbar is missing. Anyone has a hint, how I can improve it?

Slides.tsx (inside of the Slide component I'm using the IonSlide component)

import { IonSlides } from '@ionic/react';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import './Slides.css';
import Slide from '../Slide/Slide'
import SlideObject from '../../models/SlideObject';
import SlideOptsObject from '../../models/SlideOptsObject';

interface SlidesProps {
  slides: Array<SlideObject>,
  slideOpts: SlideOptsObject
};

interface SlidesState {
};


class Slides extends React.Component<SlidesProps, SlidesState> {
  private slidesRef = React.createRef<any>();

  // wenn sich die slides geaendert haben -> aktualisieren
  componentDidUpdate(prevProps: SlidesProps) {
    if (this.props.slides.length !== prevProps.slides.length) {
      // update() einkommentieren, wenn workaround gefixt, https://github.com/ionic-team/ionic/issues/18784
      // this.slidesRef.current.update();

      const workaround = async() => {
        // https://swiperjs.com/api/
        let swiper = await this.slidesRef.current.getSwiper();
        swiper.removeAllSlides();
        swiper.appendSlide(this.props.slides.map((slide, i) => {
          return ReactDOMServer.renderToString(<Slide slide={slide} key={i} />); // redundanter code
        }));
        swiper.update();
        swiper.slideTo(this.props.slideOpts.initialSlide); // zur letzten Slide sliden
      };
      workaround();
    }
  }

  render() {
    return (
      <IonSlides ref={this.slidesRef} /*pager={true}*/ scrollbar={true} options={this.props.slideOpts}>
        {this.props.slides.map((slide, i) => {
          return <Slide slide={slide} key={i} />;
        })}
      </IonSlides>
    );
  }
};

export default Slides;

Solution

  • Regarding to this post, I solved it by adding a key to the IonSlides component and removing the workaround.

    <IonSlides ref={this.slidesRef} scrollbar={true} options={this.props.slideOpts} key={this.props.slides.length}>