swiper: `Cannot convert undefined or null to object` when using `Thumbs` module

Check that this is really a bug

  • I confirm

Reproduction link

https://github.com/bnn1/swiper-issue

Bug description

When creating component from example in React app, app throws runtime error TypeError: Cannot convert undefined or null to object.

Reproduction link contains next.js app but it is possible to reproduce with pure react bootstrapped with CRA

Steps to reproduce:

  1. Create react app yarn create react-app
  2. Install swiper
  3. Create component Carousel and add the following code
code
import React, { useState } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import { Thumbs } from "swiper";
import "swiper/css";

export const Component = () => {
  // store thumbs swiper instance
  const [thumbsSwiper, setThumbsSwiper] = useState(null);

  return (
    <main>
      {/* Main Swiper -> pass thumbs swiper instance */}
      <h1>hello</h1>
      <Swiper modules={[Thumbs]} thumbs={{ swiper: thumbsSwiper || null }}>
        <SwiperSlide>1</SwiperSlide>
        <SwiperSlide>2</SwiperSlide>
        <SwiperSlide>3</SwiperSlide>
        <SwiperSlide>4</SwiperSlide>
        <SwiperSlide>5</SwiperSlide>
      </Swiper>

      {/* Thumbs Swiper -> store swiper instance */}
      {/* It is also required to set watchSlidesProgress prop */}
      <Swiper modules={[Thumbs]} watchSlidesProgress onSwiper={setThumbsSwiper}>
        {/* ... */}        <SwiperSlide>1</SwiperSlide>
        <SwiperSlide>2</SwiperSlide>
        <SwiperSlide>3</SwiperSlide>
        <SwiperSlide>4</SwiperSlide>
        <SwiperSlide>5</SwiperSlide>

      </Swiper>
    </main>
  );
};

4. Use `Component` inside `App.js` file
import { Component } from './Component';

function App() {
  return (
    <div className="App">
      <Component />
    </div>
  );
}

export default App;
  1. Run application yarn start
  2. Navigate to localhost:3000
  3. Open dev tools

Expected Behavior

No errors occur during runtime

Actual Behavior

Errors occur during runtime

Swiper version

8.1.0

Platform/Target and Browser Versions

Linux (arch), Chrome Version 100.0.4896.88 (Official Build) (64-bit)

Validations

  • Follow our Code of Conduct
  • Read the docs.
  • Check that there isn’t already an issue that request the same feature to avoid creating a duplicate.
  • Make sure this is a Swiper issue and not a framework-specific issue

Would you like to open a PR for this bug?

  • I’m willing to open a PR

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 17
  • Comments: 24

Most upvoted comments

the workaround is thumbs={{ swiper: thumbsSwiper }} replace to thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }}

I am facing with this issue as well with Nextjs 12 + React 18

the workaround is thumbs={{ swiper: thumbsSwiper }} replace to thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }}

This didn’t work for my case.

From the thumbs React demo, it has const [thumbsSwiper, setThumbsSwiper] = useState(null);

I console logged thumbsSwiper and destroyed was coming up as true. Well, the whole story is that thumbsSwiper was console logging null at first when rendering & then after another render on its own, it gave me the output:Swiper { "destroyed": true }. My guess is that the error in question came up because of that first null rendering from thumbsSwiper.

I just render my component like so: arrOfDataObjs && <MultiSliders />.

So what worked for me was adding thumbsSwiper as a condition to rendering: arrOfDataObjs && thumbsSwiper && <MultiSliders />.

I’m using create-react-app with React v16.13.1 & Swiper v8.2.4

<Swiper cssMode={true} loop={true} spaceBetween={10} navigation={true} thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }} onInit={(swiper) => { setInit(swiper); }} modules={[FreeMode, Navigation, Thumbs]} className=“mySwiper2” />

thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }}

vaqtinchalik yechim bilan thumbs={{ swiper: thumbsSwiper }} almashtiriladi thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }}

buni

vaqtinchalik yechim bilan thumbs={{ swiper: thumbsSwiper }} almashtiriladi thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }}

where do we write this?

Seems like this call is incorrect? Should be Swiper.default.defaults. There appears to be something strange happening with the exports.

extend(params, Swiper.defaults); **NOT THE SAME OBJECT BEING PASSED HERE**

function extend(target, src) {
    const noExtend = ['__proto__', 'constructor', 'prototype'];
    Object.keys(src)  **src is undefined**
        .filter((key) => noExtend.indexOf(key) < 0)
...

UPDATE: 14/10/2022 This still doesn’t work for me using Angular@14.2.6 and swiper@8.4.4. Down grading to version swiper@7.41 does fix the issue though. The issue is as described above. In version 7, Swiper seems to be a function and an object in version 8.

@nolimits4web

same problem. src is undefined. use import {Swiper} from ‘swiper/vue’. maybe something wrong in build not using esm import

// swiper/vue/get-params.js
import Swiper from 'swiper';
import { isObject, extend } from './utils.js';
import { paramsList } from './params-list.js';

function getParams(obj = {}) {
  const params = {
    on: {}
  };
  const passedParams = {};
  extend(params, Swiper.defaults); // Swiper.defaults is undefined
  extend(params, Swiper.extendedDefaults); // Swiper.extendedDefaults is undefined
  params._emitClasses = true;

The work-around thumbs={{ swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null }} works but why was this closed? And shouldn’t the docs be updated? Is it because of the missing demo? Maybe someone will be able to provide one? There are many participants in this thread.

My solution to the problem:

TS2339: Property  destroyed  does not exist on type  never

Swiper 11.05

import React, { useState } from 'react';
import { Swiper as SwiperType } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';
import { FreeMode, Navigation, Thumbs } from 'swiper/modules';
import * as S from './styles';
import detailMain2 from 'assets/img/example/detail/detail-main-2.png';
import detailMain3 from 'assets/img/example/detail/detail-main-3.png';
import detailMain4 from 'assets/img/example/detail/detail-main-4.png';
import detailMain5 from 'assets/img/example/detail/detail-main-5.jpg';

interface ImageItem {
  img: string;
}

const detailCarouselsMain: ImageItem[] = [
  { img: detailMain2 },
  { img: detailMain3 },
  { img: detailMain5 },
  { img: detailMain4 },
  { img: detailMain5 },
];

const ProductCarousel: React.FC = () => {
  const [thumbsSwiper, setThumbsSwiper] = useState<SwiperType | null>(null);

  console.log('thumbsSwiper', thumbsSwiper);

  return (
    <S.ProductCarousel>
      <Swiper
        spaceBetween={ 10 }
        navigation={ true }
        thumbs={ { swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null } }
        modules={ [FreeMode, Navigation, Thumbs] }
      >
        { detailCarouselsMain.map((instance, index) => (
          <SwiperSlide key={ instance.img + index }>
            <S.ProductCarouselImg src={ instance.img } alt={ 'alt' } />
          </SwiperSlide>
        )) }
      </Swiper>

      <Swiper
        onSwiper={ setThumbsSwiper }
        spaceBetween={ 10 }
        slidesPerView={ 4 }
        freeMode={ true }
        watchSlidesProgress={ true }
        modules={ [FreeMode, Navigation, Thumbs] }
      >
        { detailCarouselsMain.map((instance, index) => (
          <SwiperSlide key={ instance.img + index }>
            <S.ProductCarouselImg src={ instance.img } alt={ 'alt' } />
          </SwiperSlide>
        )) }
      </Swiper>
    </S.ProductCarousel>
  );
};

export default ProductCarousel;

thumbs={{swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null}}

Why is the discussion closed? Tre error is actual #5801

the answer of the MaksimAmelchenko is working