Skip to content

Commit

Permalink
fix: render state value in children render always get init one (#2634)
Browse files Browse the repository at this point in the history
  • Loading branch information
YannLynn authored Dec 16, 2024
1 parent e65e2dc commit 2c43674
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 38 deletions.
7 changes: 4 additions & 3 deletions packages/semi-foundation/carousel/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export interface CarouselAdapter<P = Record<string, any>, S = Record<string, any
setNewActiveIndex: (activeIndex: number) => void;
setPreActiveIndex: (activeIndex: number) => void;
setIsReverse: (isReverse: boolean) => void;
setIsInit: (isInit: boolean) => void
setIsInit: (isInit: boolean) => void;
getChildren: () => any[]
}

class CarouselFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<CarouselAdapter<P, S>, P, S> {
Expand Down Expand Up @@ -102,7 +103,7 @@ class CarouselFoundation<P = Record<string, any>, S = Record<string, any>> exten
}

getValidIndex(index: number): number {
const { children } = this.getStates();
const children = this._adapter.getChildren();
return (index + children.length) % children.length;
}

Expand All @@ -124,7 +125,7 @@ class CarouselFoundation<P = Record<string, any>, S = Record<string, any>> exten

handleAutoPlay(): void {
const { autoPlay } = this.getProps();
const { children } = this.getStates();
const children = this._adapter.getChildren();
const autoPlayType = typeof autoPlay;
// when user manually call the play function, force play
// only when carousel children length > 1 to start play
Expand Down
21 changes: 20 additions & 1 deletion packages/semi-ui/carousel/_story/carousel.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -517,4 +517,23 @@ export const OnlyOneChildrenNotPlay = () => (
<h3>1</h3>
</div>
</Carousel>
);
);

export const renderStateInChildren = () => {
const [curIndex, setCurIndex] = useState(0);

return (
<Carousel style={style}
autoPlay={false}
activeIndex={curIndex}
onChange={(index) => {setCurIndex(index)}}>
{[1, 2, 3, 4].map((src, index) => {
return (
<div style={contentPinkStyle} key={index}>
{curIndex}
</div>
)
})}
</Carousel>
)
};
59 changes: 25 additions & 34 deletions packages/semi-ui/carousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import isNullOrUndefined from '@douyinfe/semi-foundation/utils/isNullOrUndefined

export interface CarouselState {
activeIndex: number;
children: (ReactChild | ReactFragment | ReactPortal)[];
preIndex: number;
isReverse: boolean;
isInit: boolean
Expand All @@ -23,7 +22,7 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
static propTypes = {
activeIndex: PropTypes.number,
animation: PropTypes.oneOf(strings.ANIMATION_MAP),
arrowProps: PropTypes.object,
arrowProps: PropTypes.object,
autoPlay: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
className: PropTypes.string,
defaultActiveIndex: PropTypes.number,
Expand Down Expand Up @@ -69,7 +68,6 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {

this.state = {
activeIndex: defaultActiveIndex,
children: this.getChildren(),
preIndex: defaultActiveIndex,
isReverse: false,
isInit: true
Expand All @@ -93,6 +91,9 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
},
setIsInit: (isInit: boolean): void => {
this.setState({ isInit });
},
getChildren: (): any[] => {
return this.getChildren() as any[];
}
};
}
Expand All @@ -109,19 +110,6 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
this.handleAutoPlay();
}

componentDidUpdate(prevProps: Readonly<CarouselProps>, prevState: Readonly<CarouselState>, snapshot?: any): void {
const prevChildrenKeys = React.Children.toArray(prevProps.children).map((child) =>
isValidElement(child) ? child.key : null
);
const nowChildrenKeys = React.Children.toArray(this.props.children).map((child) =>
isValidElement(child) ? child.key : null
);

if (!isEqual(prevChildrenKeys, nowChildrenKeys)) {
this.setState({ children: this.getChildren() });
}
}

componentWillUnmount(): void {
this.foundation.destroy();
}
Expand All @@ -136,7 +124,7 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
return this.foundation.stop();
};

goTo = ( targetIndex: number): void => {
goTo = (targetIndex: number): void => {
return this.foundation.goTo(targetIndex);
};

Expand All @@ -147,7 +135,7 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
next = (): void => {
return this.foundation.next();
};

handleAutoPlay = (): void => {
if (!this.foundation.getIsControlledComponent()) {
this.foundation.handleAutoPlay();
Expand All @@ -174,7 +162,7 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {

getChildren = (): (ReactChild | ReactFragment | ReactPortal)[] => {
const { children: originChildren } = this.props;
return Children.toArray(originChildren).filter(child=>{
return Children.toArray(originChildren).filter(child => {
return React.isValidElement(child);
});
}
Expand All @@ -186,14 +174,16 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {

renderChildren = () => {
const { speed, animation } = this.props;
const { activeIndex, children, preIndex, isInit } = this.state;
const { activeIndex, preIndex, isInit } = this.state;

const children = this.getChildren();

return (
<>
{children.map((child: any, index: number) => {
const isCurrent = index === activeIndex;
const isPrev = index === this.getValidIndex(activeIndex - 1);
const isNext = index === this.getValidIndex(activeIndex + 1);
const isNext = index === this.getValidIndex(activeIndex + 1);

const animateStyle = {
transitionTimingFunction: 'ease',
Expand Down Expand Up @@ -223,12 +213,13 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
}

renderIndicator = () => {
const { children, activeIndex } = this.state;
const { activeIndex } = this.state;
const { showIndicator, indicatorType, theme, indicatorPosition, indicatorSize, trigger } = this.props;

const carouselIndicatorCls = cls({
[cssClasses.CAROUSEL_INDICATOR]: true
});
const children = this.getChildren();

if (showIndicator && children.length > 1) {
return (
Expand All @@ -250,15 +241,15 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
}

renderArrow = () => {
const { children } = this.state;
const { showArrow, arrowType, theme, arrowProps } = this.props;
const children = this.getChildren();

if (showArrow && children.length > 1) {
return (
<CarouselArrow
type={arrowType}
theme={theme}
prev={this.prev}
<CarouselArrow
type={arrowType}
theme={theme}
prev={this.prev}
next={this.next}
arrowProps={arrowProps}
/>
Expand All @@ -277,19 +268,19 @@ class Carousel extends BaseComponent<CarouselProps, CarouselState> {
});

return (
<div
<div
// role='listbox'
// tabIndex={0}
className={carouselWrapperCls}
style={style}
className={carouselWrapperCls}
style={style}
onMouseEnter={debounce(this.handleMouseEnter, 400)}
onMouseLeave={debounce(this.handleMouseLeave, 400)}
{...this.getDataAttr(this.props)}
// onMouseEnter={this.handleMouseEnter}
// onMouseLeave={this.handleMouseLeave}
// onKeyDown={e => this.foundation.handleKeyDown(e)}
// onMouseEnter={this.handleMouseEnter}
// onMouseLeave={this.handleMouseLeave}
// onKeyDown={e => this.foundation.handleKeyDown(e)}
>
<div
<div
className={cls([`${cssClasses.CAROUSEL_CONTENT}-${animation}`], {
[`${cssClasses.CAROUSEL_CONTENT}`]: true,
[`${cssClasses.CAROUSEL_CONTENT}-reverse`]: slideDirection === 'left' ? isReverse : !isReverse,
Expand Down

0 comments on commit 2c43674

Please sign in to comment.