Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf: reduce the amount of work done when rendering data
Before, even if the limit of the number of render is set, it will render one more layer of BaseLayout, which makes the performance can not be maximized, and now the optimization makes BaseLayout will not render any more, even if the number of data is 1 million, it will only render the specified amount of render. Performance has improved dramatically. fix #352, fix #362, fix #258, fix #478
- Loading branch information
Showing
6 changed files
with
183 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'react-native-reanimated-carousel': patch | ||
--- | ||
|
||
Reduce the amount of work done when rendering data. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import React from "react"; | ||
import type { FC } from "react"; | ||
import type { ViewStyle } from "react-native"; | ||
import type Animated from "react-native-reanimated"; | ||
import { useAnimatedReaction, type AnimatedStyleProp, runOnJS } from "react-native-reanimated"; | ||
|
||
import type { TAnimationStyle } from "./BaseLayout"; | ||
import { BaseLayout } from "./BaseLayout"; | ||
|
||
import type { VisibleRanges } from "../hooks/useVisibleRanges"; | ||
import { useVisibleRanges } from "../hooks/useVisibleRanges"; | ||
import type { CarouselRenderItem } from "../types"; | ||
import { computedRealIndexWithAutoFillData } from "../utils/computed-with-auto-fill-data"; | ||
|
||
interface Props { | ||
data: any[] | ||
dataLength: number | ||
rawDataLength: number | ||
loop: boolean | ||
size: number | ||
windowSize?: number | ||
autoFillData: boolean | ||
offsetX: Animated.SharedValue<number> | ||
handlerOffset: Animated.SharedValue<number> | ||
layoutConfig: TAnimationStyle | ||
renderItem: CarouselRenderItem<any> | ||
customAnimation?: ((value: number) => AnimatedStyleProp<ViewStyle>) | ||
} | ||
|
||
export const ItemRenderer: FC<Props> = (props) => { | ||
const { | ||
data, | ||
size, | ||
windowSize, | ||
handlerOffset, | ||
offsetX, | ||
dataLength, | ||
rawDataLength, | ||
loop, | ||
autoFillData, | ||
layoutConfig, | ||
renderItem, | ||
customAnimation, | ||
} = props; | ||
|
||
const visibleRanges = useVisibleRanges({ | ||
total: dataLength, | ||
viewSize: size, | ||
translation: handlerOffset, | ||
windowSize, | ||
loop, | ||
}); | ||
|
||
const [displayedItems, setDisplayedItems] = React.useState<VisibleRanges>(null!); | ||
|
||
useAnimatedReaction( | ||
() => visibleRanges.value, | ||
ranges => runOnJS(setDisplayedItems)(ranges), | ||
[visibleRanges], | ||
); | ||
|
||
if (!displayedItems) | ||
return null; | ||
|
||
return ( | ||
<> | ||
{ | ||
data.map((item, index) => { | ||
const realIndex = computedRealIndexWithAutoFillData({ | ||
index, | ||
dataLength: rawDataLength, | ||
loop, | ||
autoFillData, | ||
}); | ||
|
||
const { negativeRange, positiveRange } = displayedItems; | ||
|
||
const shouldRender = (index >= negativeRange[0] && index <= negativeRange[1]) | ||
|| (index >= positiveRange[0] && index <= positiveRange[1]); | ||
|
||
if (!shouldRender) | ||
return null; | ||
|
||
return ( | ||
<BaseLayout | ||
key={index} | ||
index={index} | ||
handlerOffset={offsetX} | ||
visibleRanges={visibleRanges} | ||
animationStyle={customAnimation || layoutConfig} | ||
> | ||
{({ animationValue }) => | ||
renderItem({ | ||
item, | ||
index: realIndex, | ||
animationValue, | ||
}) | ||
} | ||
</BaseLayout> | ||
); | ||
}) | ||
} | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.