Swiper js for React does not render children properly

Viewed 1101

First of all, I use React, Gatsby and Swiperjs.

I have problem with rendering children into Swiper component. I use swiper in two places (Blog and Portfolio sections) so I created CardsSlider component to reuse it. I use two types of similar components so I use Higher Order Component to surround each card component with SwiperSlide. Then I iterate through each data to generate cards surrounded with SwiperSlide component as children prop for CardsSlider which is basically Swiper. Problem is: SwiperSlide cards are not wrapped with SwiperWrapper component what you can see in ss of devtools down below.

HTML Tags

Blog component:

const Blog = () => {
  const { postImage } = useStaticQuery(...)
  const CardsData = [
    {
      title: 'Post1',
      description:
        'Lorem ipsum dolor sit amet consectetur adipisicing elit. Harum veritatis in reiciendis sit facere enim modi, libero placeat consectetur eaque?',
      image: postImage,
    }, 
     ...
  ];

  const BlogPostCardWithSlider = withSlider(BlogPostCard);

  return (
    <StyledSection>
      <StyledHeader text="BLOG" />
      <CardsSlider pagination>
        {CardsData.map((data) => (
          <BlogPostCardWithSlider key={data.title} data={data} />
        ))}
      </CardsSlider>
      <Button dark text="ZOBACZ WSZYSTKIE WPISY" />
    </StyledSection>
  );
};

export default Blog;

Portfolio component:

 const Portfolio = () => {
  const { projectImage } = useStaticQuery(...);

  const CardsData = [
    {
      title: 'Project1',
      description:
        'Lorem ipsum dolor sit amet consectetur adipisicing elit. Harum veritatis in reiciendis sit facere enim modi, libero placeat consectetur eaque?',
      image: projectImage,
      techStack: ['bootstrap', 'nodejs', 'sequelize', 'react', 'mssql'],
    },
    ...
  ];

  const ProjectCardWithSlider = withSlider(ProjectCard);

  return (
    <StyledSection odd>
      <StyledHeader text="PORTFOLIO" />
      <CardsSlider navigation loop>
        {CardsData.map((data) => (
          <ProjectCardWithSlider key={data.title} data={data} />
        ))}
      </CardsSlider>
    </StyledSection>
  );
};

export default Portfolio;

withSlider HOC:

import React from 'react';
import { SwiperSlide } from 'swiper/react';

const slideStyles = {
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center',
};

const withSlider = (WprappedComponent) => (props) => (
  <SwiperSlide style={slideStyles}>
    <WprappedComponent {...props} />
  </SwiperSlide>
);

export default withSlider;

CardsSlider component:

import React from 'react';
import styled from 'styled-components';
import { Swiper } from 'swiper/react';
import SwiperCore, { Pagination, Navigation } from 'swiper';
import 'swiper/swiper-bundle.css';

SwiperCore.use([Pagination, Navigation]);

const SwiperWrapper = styled(Swiper)`
  ...
`;

const CardsSlider = ({ children, pagination, ...rest }) => {
  const params = {
    spaceBetween: 0,
    pagination: pagination && { clickable: true },
    ...rest,
  };

  return <SwiperWrapper {...params}>{children}</SwiperWrapper>;
};

Fun fact is, when i map children like this:

{children.map((child) => <SwiperSlide>{child}<SwiperSlide/>)}

It render in correct place.

Thank you for help.

1 Answers

I have the same exact problem when dealing with a minimum example. Seems the children are added AFTER the wrapper, if they are not SwiperSlides. My suggestion is to keep SwiperSlide as direct children of Swiper component, and use HOC for the content of the slides. At least, seems the only thing working for me, and i'm fine with it as i dont want to lose much time on the internals of Swiper.

Related