Hope you’re all doing well. I am encountering an issue with a card based carousel, that for the life of me I haven’t been able to get to the bottom of it.

There is obviously a Carousel. When a user hits ‘next’ I want the present card to ‘slide’ off of the carousel (to the right), and then a new card to follow it on the left. I ideally want the cards to almost appear as if they are on a wheel, so that as one leaves, the other enters. The way the “Translate” and “Transition” properties are configured though, what seems to be happening is that the card is some how being reset, and the card is sliding from the right to the center. That is to say the card is disappearing, and then coming in from the right to the center.

  • What have you done to address this?: As mentioned, my current perception is that when the button ‘next’ is clicked, the changing of the ‘transition’ property is re-invoked and thereby changes. This is of course happening at the same time the translate property is being changed. I tried to add additional checks to the code, so that the code would test for the type of sliding taking place, so that it wouldn’t reset the transition property was set.
  • Have you reviewed any other articles in an attempt to address this?: Yes, I have. I reviewed this article among others.
  • Can we see the code?: Yes the code is below with some guiding thoughts and an articulation of its structure. In addition to this though, I have also included a link to the github repo, and the actual website (such as it is). Please click on the second “Questionnaire” button.
  • What is the end result you’re looking to achieve?: As mentioned, I’d like the card to slide out on the page when the page starts, and then when “next” is clicked, I’d like the present card to slide off of the page, and then have the next card slide onto the page. (Right now, there is only one card and it is hard coded into the code – as I’ve been focusing on moving the card to the right from the center)

The Code:

  • “Carousel.js” contains the actual body of the code. The functions incurring the movement, the state of the component, etc.. etc…
export default class Carousel extends Component {
    constructor(props) {
        super(props);
        this.state = {
            position: 0,
            direction: props.children.length === 2 ? "prev" : "next",
            sliding: false
          };
    }
    getOrder(itemIndex) {
        const { position } = this.state;
        const { children } = this.props;
        const numItems = children.length;

        if (numItems === 2) return itemIndex;

        if (itemIndex - position < 0)
          return numItems - Math.abs(itemIndex - position);
        return itemIndex - position;
      }

    doSliding = (direction, position) => {
        this.setState({
          sliding: true,
          direction,
          position
        });

        setTimeout(() => {
          this.setState({
            sliding: false
          });
        }, 50);
    };

    nextSlide = () => {
        const { position } = this.state;
        const { children } = this.props;
        const numItems = children.length;

        if (numItems === 2 && position === 1) return;

        this.doSliding("next", position === numItems - 1 ? 0 : position + 1);
    };

    prevSlide = () => {
        const { position } = this.state;
        const { children } = this.props;
        const numItems = children.length;

        if (numItems === 2 && position === 0) return;

        this.doSliding("prev", position === 0 ? numItems - 1 : position - 1);
    };

    render() {
        const { children } = this.props;
        const { sliding, direction, position } = this.state;

        const childrenWithProps = Children.map(children, child =>
          cloneElement(child, {
            numSlides: children.length || 1
          })
        );

        return (
          <div>
            <Wrapper>
              <CarouselContainer
                sliding={sliding}
                direction={direction}
                numSlides={childrenWithProps.length}
              >
                {childrenWithProps.map((child, index) => (
                  <CarouselSlot
                    key={index}
                    order={this.getOrder(index)}
                    numSlides={childrenWithProps.length}
                    position={position}
                  >
                    {child}
                  </CarouselSlot>
                ))}
              </CarouselContainer>
            </Wrapper>
            <button onClick={() => this.prevSlide()}>Prev</button>
            <button onClick={() => this.nextSlide()}>Next</button>
          </div>
        );
      }
}

file ‘carousel-css-styles.js’
This file controls the actual styles themselves. The functionality in this file is controlled by the library, “styled-components”. This file actually controls the CSS, thereby attaching the different CSS attributes to the ‘card’ based on the props that are passed into it by the component. The component obviously uses state to control and monitor these states, and they are passed into the various objects in this code body, so that their CSS attributes change based on what the state of the component is. I have only attached the code from the relevant object in this case.

export const CarouselContainer = styled.div`
  display: flex;
  margin: 0 0 20px 20px;
  transition: ${props => (transitionDetermination(props))};
  transform: ${props => {
    //The line below seems to control the default position of the card.
    if (!props.sliding) return "translateX(0rem)";
    //This line controls the "Prev" button.
    if (props.direction === "prev")
      return "translateX(calc(2 * (-80% - 20px)))";
    //This line controls the "Next" button.
    if(props.direction === "next")
        return "translate(50rem)"
    return "translateX(0%)";
  }};
`;

Any help would be greatly appreciated.