@@ -11,6 +11,7 @@ import {
1111 Platform ,
1212 FlatList ,
1313 ListRenderItemInfo ,
14+ ViewToken ,
1415} from 'react-native' ;
1516import TabBarItem , { Props as TabBarItemProps } from './TabBarItem' ;
1617import TabBarIndicator , { Props as IndicatorProps } from './TabBarIndicator' ;
@@ -247,6 +248,8 @@ const renderIndicatorDefault = (props: IndicatorProps<Route>) => (
247248
248249const getTestIdDefault = ( { route } : Scene < Route > ) => route . testID ;
249250
251+ const MEASURE_PER_BATCH = 10 ;
252+
250253export default function TabBar < T extends Route > ( {
251254 getLabelText = getLabelTextDefault ,
252255 getAccessible = getAccessibleDefault ,
@@ -279,8 +282,9 @@ export default function TabBar<T extends Route>({
279282} : Props < T > ) {
280283 const [ layout , setLayout ] = React . useState < Layout > ( { width : 0 , height : 0 } ) ;
281284 const [ tabWidths , setTabWidths ] = React . useState < Record < string , number > > ( { } ) ;
282- const flatListRef = React . useRef < FlatList > ( null ) ;
285+ const flatListRef = React . useRef < FlatList | null > ( null ) ;
283286 const isFirst = React . useRef ( true ) ;
287+ const measuredTabWidhtsCount = React . useRef ( 0 ) ;
284288 const scrollAmount = useAnimatedValue ( 0 ) ;
285289 const measuredTabWidths = React . useRef < Record < string , number > > ( { } ) ;
286290
@@ -298,7 +302,14 @@ export default function TabBar<T extends Route>({
298302
299303 const hasMeasuredTabWidths =
300304 Boolean ( layout . width ) &&
301- routes . every ( ( r ) => typeof tabWidths [ r . key ] === 'number' ) ;
305+ routes
306+ . slice (
307+ 0 ,
308+ routes . length > MEASURE_PER_BATCH
309+ ? measuredTabWidhtsCount . current
310+ : routes . length
311+ )
312+ . every ( ( r ) => typeof tabWidths [ r . key ] === 'number' ) ;
302313
303314 React . useEffect ( ( ) => {
304315 if ( isFirst . current ) {
@@ -373,13 +384,25 @@ export default function TabBar<T extends Route>({
373384 ? ( e : LayoutChangeEvent ) => {
374385 measuredTabWidths . current [ route . key ] = e . nativeEvent . layout . width ;
375386
376- // When we have measured widths for all of the tabs, we should updates the state
377- // We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
387+ // If we have more than 10 routes divide updating tabWidths into multiple batches. Here we update only first batch of 10 items.
378388 if (
389+ routes . length > MEASURE_PER_BATCH &&
390+ index === MEASURE_PER_BATCH &&
391+ routes
392+ . slice ( 0 , MEASURE_PER_BATCH )
393+ . every (
394+ ( r ) => typeof measuredTabWidths . current [ r . key ] === 'number'
395+ )
396+ ) {
397+ setTabWidths ( { ...measuredTabWidths . current } ) ;
398+ measuredTabWidhtsCount . current = MEASURE_PER_BATCH ;
399+ } else if (
379400 routes . every (
380401 ( r ) => typeof measuredTabWidths . current [ r . key ] === 'number'
381402 )
382403 ) {
404+ // When we have measured widths for all of the tabs, we should updates the state
405+ // We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
383406 setTabWidths ( { ...measuredTabWidths . current } ) ;
384407 }
385408 }
@@ -494,6 +517,22 @@ export default function TabBar<T extends Route>({
494517 [ scrollAmount ]
495518 ) ;
496519
520+ const handleViewableItemsChanged = React . useCallback (
521+ ( { changed } : { changed : ViewToken [ ] } ) => {
522+ if ( routes . length <= MEASURE_PER_BATCH ) {
523+ return ;
524+ }
525+ // Get next vievable item
526+ const [ item ] = changed ;
527+ const index = item . index || 0 ;
528+ if ( item . isViewable && index >= measuredTabWidhtsCount . current ) {
529+ setTabWidths ( { ...measuredTabWidths . current } ) ;
530+ measuredTabWidhtsCount . current += MEASURE_PER_BATCH ;
531+ }
532+ } ,
533+ [ routes . length ]
534+ ) ;
535+
497536 return (
498537 < Animated . View onLayout = { handleLayout } style = { [ styles . tabBar , style ] } >
499538 < Animated . View
@@ -513,6 +552,7 @@ export default function TabBar<T extends Route>({
513552 position,
514553 layout,
515554 navigationState,
555+ hasMeasuredTabWidths,
516556 jumpTo,
517557 width : isWidthDynamic
518558 ? 'auto'
@@ -549,6 +589,7 @@ export default function TabBar<T extends Route>({
549589 scrollEventThrottle = { 16 }
550590 renderItem = { renderItem }
551591 onScroll = { handleScroll }
592+ onViewableItemsChanged = { handleViewableItemsChanged }
552593 ref = { flatListRef }
553594 testID = { testID }
554595 />
0 commit comments