Home > OS >  react-transition-group does not animate
react-transition-group does not animate

Time:04-04

I use React and tranct-transition-group to write carousel components

But I encountered the problem that the animation does not take effect. The code is as follows

Link https://stackblitz.com/edit/react-ts-mi8mwj?file=Carousel.tsx

Carousel.tsx

import React, { FC, Fragment, ReactNode, useMemo, useState } from 'react';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
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);
  };
  return (
    <Fragment>
      <button onClick={onPrev}>prev</button>
      <button onClick={onNext}>next</button>
      <div className="g-carousel-wrapper">
        <div className="g-carousel-window">
          <TransitionGroup className="item">
            {React.Children.map(children, (child, index) => {
              const childElement = child as FC<ItemProps>;
              if(child.type !== CarouselItem) throw new Error('必须是Item')
              return (
                <CSSTransition classNames="item" timeout={300} key={index}>
                  {React.cloneElement(childElement, {
                    index,
                    style: { display: curIndex !== index && 'none' },
                  })}
                </CSSTransition>
              );
            })}
          </TransitionGroup>
        </div>
      </div>
    </Fragment>
  );
};

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

const Carousel: CarouselType = Component as CarouselType;

Carousel.Item = CarouselItem;

export default Carousel;

CarouselItem.tsx

import React, { CSSProperties, FC } from 'react';

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

const carouselItem: FC<ItemProps> = (props) => {
  const { children, style } = props;
  return (
    <div className="g-carousel-item" style={style}>
      {children}
    </div>
  );
};

export default carouselItem;

I don't understand why not only there is no animation effect but also the className of CSSTransition does not exist, it seems that react-transition-group does not take effect thanks

CodePudding user response:

I think we don't need to use the TransitionGroup component. CSSTransition itself supports a in prop, we can use this prop to control it's visibility.

So first, Add the in condition to the CSSTransition:

<CSSTransition
  in={curIndex === index}
  classNames="item"
  timeout={300}
  key={index}
>

And then, just remove the TransitionGroup:

<div className="g-carousel-wrapper">
  <div className="g-carousel-window">
    {React.Children.map(children, (child, index) => {
      const childElement = child as FC<ItemProps>;
      if (child.type !== CarouselItem) throw new Error('必须是Item');
      return (
        <CSSTransition
          in={curIndex === index}
          classNames="item"
          timeout={300}
          key={index}
        >
          {React.cloneElement(childElement, {
            index,
            style: { display: curIndex !== index && 'none' },
          })}
        </CSSTransition>
      );
    })}
  </div>
</div>

It should be working now: https://stackblitz.com/edit/react-ts-kqed2n?file=Carousel.tsx

  • Related