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