Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Children does not render properly (after wrapper component) #4413

Closed
tobiaszciesielski opened this issue Apr 7, 2021 · 15 comments · Fixed by #5954
Closed

Children does not render properly (after wrapper component) #4413

tobiaszciesielski opened this issue Apr 7, 2021 · 15 comments · Fixed by #5954
Labels

Comments

@tobiaszciesielski
Copy link

Hello, I have already posted on stackoverflow about rendering children in swiperjs using React.

https://stackoverflow.com/questions/66993033/swiper-js-for-react-does-not-render-children-properly
I use:

"gatsby": "^3.0.1",
"react": "^17.0.1",
"swiper": "^6.5.0",

What You Did

I want to render children like this:
<Swiper>{children}<Swiper/>
But children are rendered after swiper wrapper.

Expected Behavior

I want to pass all children and render them inside Swiper wrapper because I fetch data from external source (headless cms)

Actual Behavior

Swiper Slides are rendered after Swiper component what makes cards invisible in page content.

The code you can see in stack overflow and this commit of my project
tobiaszciesielski/tciesielski.pl@5500865

@alicerocheman
Copy link

alicerocheman commented Sep 1, 2021

Same issue.

react

Slider.tsx

import { FC, useMemo } from 'react';
import { Swiper } from 'swiper/react';
import { Navigation, Scrollbar, A11y, Keyboard } from 'swiper';

const breakpoints = {
  1100: {
    slidesPerView: 4,
  },
  768: {
    slidesPerView: 3,
  },
  464: {
    slidesPerView: 2,
  },
};

const Slider: FC = ({ children }) => {
  return (
    <>
      <Swiper
        wrapperTag="ul"
        modules={[Navigation, Scrollbar, A11y, Keyboard]}
        navigation={{ prevEl: '.prev', nextEl: '.next' }}
        slidesPerView={1}
        spaceBetween={16}
        breakpoints={breakpoints}
      >
        {children}
      </Swiper>
    </>
  );
};

export default Slider;

Component.tsx

return (
  <Slider>
    {categories.map((category) => (
      <>
        category.list.map(el => (<SwiperSlide tag="li">{el.content}</SwiperSlide>))
      </>
    )}
  </Slider>
);

renders:

<div class="swiper swiper-initialized swiper-horizontal swiper-android w-full">
  <ul
    class="swiper-wrapper"
    id="swiper-wrapper-dc73d3daab7e6247"
    aria-live="polite"
    style="transform: translate3d(0px, 0px, 0px)"
  ></ul>
  <span
    class="swiper-notification"
    aria-live="assertive"
    aria-atomic="true"
  ></span
  ><span
    class="swiper-notification"
    aria-live="assertive"
    aria-atomic="true"
  ></span>
  <li class="swiper-slide"></li>
  <li class="swiper-slide"></li>
  <li class="swiper-slide"></li>
  <li class="swiper-slide"></li>
  <li class="swiper-slide"></li>
  <li class="swiper-slide"></li>
</div>·

Expected behavior

slides render inside the swiper-wrapper

Current behavior

slides render outside the swiper-wrapper

@jomarquez21
Copy link

jomarquez21 commented Nov 10, 2021

Same error in 7.2.0 version

@jomarquez21
Copy link

@nolimits4web Can you confirm if this is a bug or a misinterpretation of the documentation?

@jomarquez21
Copy link

@tobiaszciesielski Can you confirm if this is a bug or a misinterpretation of the documentation?

@github-actions
Copy link

Hello @tobiaszciesielski. Please provide a online reproduction by codesandbox or a minimal GitHub repository. You can fork one of our demos in codesandbox to get start. Issues labeled by missing demo will be closed if no activities in 3 days.

@jomarquez21
Copy link

@nolimits4web Could you remove the "missing demo" tag?

@williamgoulois
Copy link

@jomarquez21 I encoutered same issue when i tried to use subcomponents and here is the workaroud i found :

Carousel.tsx

import React, { ReactNode } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import SwiperCore, { Keyboard, Mousewheel, Navigation } from 'swiper'

type CarouselComposition = {
  Item: typeof Item
}

export type CarouselProps = {
  children: ReactNode
}

SwiperCore.use([Navigation, Mousewheel, Keyboard])

export const Carousel: React.VFC<CarouselProps> & CarouselComposition = ({ children }) => {
  return (
    <Swiper>
      {/* workaround because swiper needs SwiperSlide as direct children
      @see https://github.com/nolimits4web/swiper/issues/4413
      @see https://github.com/nolimits4web/swiper/issues/4084
      */}
      {React.Children.map(children, (child: ReactNode) => (
        <SwiperSlide>{child}</SwiperSlide>
      ))}
    </Swiper>
  )
}

type ItemProps = {
  children: ReactNode
}
const Item = ({ children }: ItemProps) => {
  return <>{children}</>
}
Carousel.Item = Item

Component.tsx

...
return  (
  <Carousel>
    {Array.from(Array(10).fill(0)).map((_, i) => {
      return (
        <Carousel.Item key={i}>
            Slide {i}
        </Carousel.Item>
      )
    })}
  </Carousel>
)
...

@jomarquez21
Copy link

hi! @williamgoulois, I also used a workaround a bit similar to your code.

{items.map((item, index) => {
  // `Swiper` to render the slider items requires its children property to be a collection of `SwiperSlider` avoiding being able to create reusable slider components.
  // This workaround is created to assign a key to each `SwiperSlider`
  /** {@todo This workaround should be removed when this issue https://github.com/nolimits4web/swiper/issues/4413 is resolved}. */

  return (
    <SwiperSlide key={`slide_${index}_${item.key}`}>
      {React.cloneElement(item)}
    </SwiperSlide>
  )
})}

@im-ironclad
Copy link

im-ironclad commented Jan 11, 2022

In case it helps anyone, I just recently faced this issue as well but in this context:

I was pulling from different components that each were wrapped in a SwiperSlide (inside the component). Reading up on the above shows that Swiper wants the SwiperSlides to be a direct child so to get it working I removed the SwiperSlide inside each component and wrapped them with SwiperSlide outside of the component, inside the Carousel component.

From

Carousel.tsx

case 'newsArticles_default_Entry':
  return (
      <NewsArticleSlide content={content} />
  );
case 'podcasts_default_Entry':
  return (
      <PodcastSlide content={content} />
  );

Slide.tsx

return (
    <SwiperSlide key={id}>
        <article>
            ...markup
        </article>
    </SwiperSlide>
  )

To

Carousel.tsx

case 'newsArticles_default_Entry':
  return (
    <SwiperSlide key={content.id}>
      <NewsArticleSlide content={content} />
    </SwiperSlide>
  );
case 'podcasts_default_Entry':
  return (
    <SwiperSlide key={content.id}>
      <PodcastSlide content={content} />
    </SwiperSlide>
  );

Slide.tsx

return (
    <article>
        ...markup
    </article>
  )

@jomarquez21
Copy link

@nolimits4web is this considered an error? If this is a bug, can you add the corresponding tag?

@msoyka
Copy link

msoyka commented Jan 25, 2022

Had the same issue, and fixed it with an even simpler solution. Let me know if you see any concerns.

All I needed to do was change the displayName of my 'custom slide' component to match the "SwiperSlide" component so the parent "Swiper" thinks the direct child is "SwiperSlide".

export const BannerSliderSlide = () => {
  return (
    <SwiperSlide>
          // Add custom code here...
    </SwiperSlide>
  );
};

BannerSliderSlide.displayName = 'SwiperSlide'; <-- ** ADDED THIS **

@isaacbatst
Copy link

isaacbatst commented Feb 18, 2022

Thanks for the solution @msoyka.

Sharing a 'deeper slides' situation here. Just the first level needs the edit.

// Root
<Swiper>
  <SwiperSlide className={styles.planningTypesSlide}> // not nested, no problem at all
     <PlanningTypesSlide />  
  </SwiperSlide>
  <NestedSlides/> // displayName needs editing
</Swiper>
// NestedSlides.jsx
<>
  <SwiperSlide className={styles.planningTypesSlide}> // not nested, no problem at all
     <AnotherCustomSlide />  
  </SwiperSlide>
  <DeeperNestedSlides /> // surprisingly, no need to edit displayName here
</>

@rardoz
Copy link

rardoz commented Apr 5, 2022

This makes me really sad.

@michaelschufi
Copy link

Had the same issue. Thanks for the workaround!

Two points:

  • Adding it to the docs would help a lot with troubleshooting.
  • The workaround makes debugging the component tree and debugging in general (everywhere where the display name of a component is used) more difficult.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants