反应过渡组没有动画

react-transition-group does not animate

我使用 React 和 tranct-transition-group 编写轮播组件

但是遇到了动画不生效的问题。代码如下

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;

不明白为什么不仅没有动画效果而且CSSTransition的className也不存在,好像react-transition-group没有生效谢谢

我认为我们不需要使用 TransitionGroup 组件。 CSSTransition本身支持一个in属性,我们可以使用这个属性来控制它的可见性。

所以首先,将 in 条件添加到 CSSTransition:

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

然后,只需删除 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>

它现在应该可以工作了:https://stackblitz.com/edit/react-ts-kqed2n?file=Carousel.tsx