fix re-render previous nodes on state change

master
Hasan Genc 4 years ago
parent 4160d761a0
commit edbd72a679
  1. 5
      src/components/carousel/defaultProps.ts
  2. 90
      src/components/carousel/index.tsx
  3. 5
      src/helpers/index.ts
  4. 8
      src/hooks/index.ts
  5. 16
      src/styles/slider/styles.module.css.d.ts
  6. 34
      src/styles/styles.module.css.d.ts

@ -13,7 +13,6 @@ export const defaultProps: Required<CarouselProps> = {
useArrowKeys: false,
a11y: {},
dynamic: false,
beforeChange: null,
afterChange: null,
extraItems: [],
paginationCallback: null,
pageCount: 0,
};

@ -1,4 +1,10 @@
import React, { useState, FunctionComponent, KeyboardEvent, useEffect } from 'react';
import React, {
useState,
FunctionComponent,
KeyboardEvent,
useEffect,
useRef,
} from 'react';
import { Arrow } from '../arrow';
import { ItemProvider } from '../item';
import {
@ -13,6 +19,7 @@ import {
import { SlideDirection, Item, ArrowKeys } from '../../types/carousel';
import { defaultProps } from './defaultProps';
import styles from '../../styles/styles.module.css';
import { usePrevious } from '../../hooks';
export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselProps) => {
const props: Required<CarouselProps> = { ...defaultProps, ...userProps };
@ -29,40 +36,35 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
const [showArrow, setShowArrow] = useState(
getShowArrow(props.children.length, props.show, props.infinite, current),
);
const [dynamicElements, setDynamicElements] = useState<Item[]>(userProps.children);
/*useEffect(() => {
if (Array.isArray(props.extraItems) && props.extraItems.length > 0) {
const elements = dynamicElements.length > 0 ? dynamicElements : props.children;
setDynamicElements(elements.concat(props.extraItems));
}
}, [props.extraItems]);*/
useEffect(() => {
if (dynamicElements.length > props.children.length) {
slide(SlideDirection.Right, true);
}
}, [dynamicElements]);
const prevChildren = usePrevious<Item[]>(userProps.children);
const [page, setPage] = useState<number>(0);
const itemsRef = useRef(initItems(props.children, props.slide, props.infinite));
const isPaginating = useRef(false);
if (props.dynamic) {
useEffect(() => {
console.log({
children: userProps.children,
dynamicElements,
});
const newItems = updateNodes(
items,
dynamicElements,
itemsRef.current,
props.children,
prevChildren,
props.slide,
props.infinite,
);
console.log({ newItems });
setItems(newItems);
}, [userProps.children, dynamicElements]);
itemsRef.current = newItems;
if (
page < props.pageCount &&
prevChildren &&
prevChildren?.length < props.children.length
) {
slide(SlideDirection.Right);
setPage(page + 1);
}
}, [props.children]);
}
const slide = async (direction: SlideDirection, cb?: boolean) => {
const slide = (direction: SlideDirection) => {
if (
animation.isSliding ||
(direction === SlideDirection.Right && !showArrow.right) ||
@ -71,19 +73,18 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
return;
}
const dynamicElementsExists = dynamicElements.length > 0;
if (!cb && props.beforeChange) {
const extraItems = await props.beforeChange(direction);
if (Array.isArray(extraItems) && extraItems.length > 0) {
const elements =
dynamicElements.length > 0 ? dynamicElements : props.children;
setDynamicElements(elements.concat(extraItems));
return;
}
if (
props.paginationCallback &&
direction === SlideDirection.Right &&
page < props.pageCount - 1 &&
!isPaginating.current
) {
isPaginating.current = true;
props.paginationCallback(direction);
return;
}
const elements = dynamicElementsExists ? dynamicElements : props.children;
const elements = props.children;
const next = getCurrent(current, props.slide, elements.length, direction);
const rotated = props.infinite
@ -91,6 +92,7 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
: items;
if (props.infinite && direction === SlideDirection.Right) {
setItems(rotated);
itemsRef.current = rotated;
}
setAnimation({
transform:
@ -102,7 +104,13 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
setShowArrow(getShowArrow(elements.length, props.show, props.infinite, next));
setTimeout(() => {
if (props.infinite) {
setItems(cleanItems(rotated, props.slide, direction));
const cleanedItems = cleanItems(
direction === SlideDirection.Right ? itemsRef.current : rotated,
props.slide,
direction,
);
setItems(cleanedItems);
itemsRef.current = cleanedItems;
}
setAnimation({
transform: props.infinite
@ -113,6 +121,7 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
isSliding: false,
});
}, props.transition * 1_0_0_0);
isPaginating.current = false;
};
const widthCallBack = (calculatedWidth: number) => {
@ -164,7 +173,7 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
<ItemProvider
{...props}
transition={animation.transition}
items={items}
items={itemsRef.current}
transform={animation.transform}
slideCallback={slideCallback}
dragCallback={dragCallback}
@ -190,9 +199,8 @@ export interface CarouselProps {
useArrowKeys?: boolean;
a11y?: { [key: string]: string };
dynamic?: boolean;
beforeChange?: ((direction: SlideDirection) => Promise<any[] | null>) | null;
afterChange?: ((direction: SlideDirection) => void) | null;
extraItems?: any[];
paginationCallback?: ((direction: SlideDirection) => any) | null;
pageCount?: number;
}
export interface CarouselState {

@ -147,9 +147,14 @@ export function getOuterWidth(el: HTMLElement) {
export function updateNodes(
oldItems: Item[],
newItems: Item[],
prevChildren: Item[] | undefined,
slide: number,
infinite: boolean,
): Item[] {
if (prevChildren && prevChildren.length < newItems.length) {
return initItems(newItems, slide, infinite);
}
const matchedItems = oldItems.map((oldItem) => {
return newItems.find((newItem) => oldItem.key === newItem.key) as Item;
});

@ -13,3 +13,11 @@ export const useWindowWidthChange = (callBack: (changed: number) => any) => {
}, []);
return;
};
export const usePrevious = <T>(value: T) => {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
});
return ref.current;
}

@ -1,10 +1,10 @@
export const sliderBase: string;
export const slider: string;
export const sliding: string;
export const sliderBase: string
export const slider: string
export const sliding: string
interface Namespace {
sliderBase: string;
slider: string;
sliding: string;
"sliderBase": string,
"slider": string,
"sliding": string,
}
declare const stylesModule: Namespace;
export default stylesModule;
declare const stylesModule: Namespace
export default stylesModule

@ -1,19 +1,19 @@
export const carouselBase: string;
export const itemProvider: string;
export const itemContainer: string;
export const itemTracker: string;
export const carouselArrow: string;
export const carouselBase: string
export const itemProvider: string
export const itemContainer: string
export const itemTracker: string
export const carouselArrow: string
interface Namespace {
carouselBase: string;
'carousel-base': string;
itemProvider: string;
'item-provider': string;
itemContainer: string;
'item-container': string;
itemTracker: string;
'item-tracker': string;
carouselArrow: string;
'carousel-arrow': string;
"carouselBase": string,
"carousel-base": string,
"itemProvider": string,
"item-provider": string,
"itemContainer": string,
"item-container": string,
"itemTracker": string,
"item-tracker": string,
"carouselArrow": string,
"carousel-arrow": string,
}
declare const stylesModule: Namespace;
export default stylesModule;
declare const stylesModule: Namespace
export default stylesModule

Loading…
Cancel
Save