'Question about the animation effect of the React carousel component

I wrote a carousel component with react and react-transition-group, but the animation of the carousel is not working properly. When the image changes from 0 to 1, the 0 will disappear immediately, instead of waiting for the animation to end and then disappear.

The Code Link is as follow

https://stackblitz.com/edit/react-ts-eawtuk?file=CarouselItem.tsx

The core codes are as follow

Carousel Component

import React, {
  FC,
  Fragment,
  ReactNode,
  useMemo,
  useState,
} from 'react';
import CarouselItem, { ItemProps } from './CarouselItem';
import './Carousel.scss';

export interface Props {}

const Component: FC<Props> = (props) => {
  const { children } = props;
  const [curIndex, setCurIndex] = useState(1);
  const length = useMemo(() => {
    return Array.from(children as ReactNode[]).length;
  }, [children]);
  const onNext = () => {
    setCurIndex((curIndex + 1 + length) % length);
  };
  const onPrev = () => {
    setCurIndex((curIndex - 1 + length) % length);
  };
  setTimeout(onNext, 3000);
  return (
    <Fragment>
      <button onClick={onPrev}>prev</button>
      <button onClick={onNext}>next</button>
      <div className="g-carousel">
        <div className="g-carousel-window">
          <div className="g-carousel-wrapper">
            {React.Children.map(children, (child, index) => {
              const ChildElement = child as FC<ItemProps>;
              if (child.type !== CarouselItem) throw new Error('必须是Item');
              return React.cloneElement(ChildElement, { index, curIndex });
            })}
          </div>
        </div>
      </div>
    </Fragment>
  );
};

type CarouselType = {
  Item: FC<ItemProps>;
} & FC<Props>;

const Carousel: CarouselType = Component as CarouselType;

Carousel.Item = CarouselItem;

export default Carousel;

CarouselItem Component

import React, { CSSProperties, FC, Fragment, useMemo } from 'react';
import { CSSTransition } from 'react-transition-group';

export interface ItemProps {
  curIndex?: number;
  index?: number;
  style?: CSSProperties;
}

const carouselItem: FC<ItemProps> = (props) => {
  const { children, index, curIndex } = props;
  const visible = useMemo(() => curIndex === index, [curIndex]);
  return (
    <Fragment>
      <CSSTransition
        in={visible}
        classNames="carousel"
        timeout={500}
        key={index}
      >
        <div
          className="g-carousel-item"
          style={{ display: curIndex !== index && 'none' }}
        >
          {children}
        </div>
      </CSSTransition>
    </Fragment>
  );
};

export default carouselItem;

And css

.g-carousel {
  &-window {
    overflow: hidden;
  }
  &-wrapper {
    position: relative;
  }
}

.carousel-exit {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
.carousel-enter,
.carousel-exit {
  transition: all 0.5s;
}
.carousel-enter-active {
  transform: translateX(-100%);
}
.carousel-enter.reverse {
  transform: translateX(100%);
}
.carousel-exit-done {
  transform: translateX(100%);
}
.carousel-exit-done.reverse {
  transform: translateX(-100%);
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source