Skip to content
This repository was archived by the owner on Nov 27, 2022. It is now read-only.

Commit 33fd808

Browse files
jtomaszewskisatya164
authored andcommitted
feat: add renderTabBarItem prop to TabBar
1 parent 02b08e2 commit 33fd808

File tree

4 files changed

+63
-46
lines changed

4 files changed

+63
-46
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ Function which takes an object with the current route, focused status and color
527527
/>
528528
```
529529

530+
##### `renderTabBarItem`
531+
532+
Function which takes a `TabBarItemProps` object and returns a custom React Element to be used as a tab button.
533+
530534
##### `renderIndicator`
531535

532536
Function which takes an object with the current route and returns a custom React Element to be used as a tab indicator.

src/TabBar.tsx

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
Platform,
1212
} from 'react-native';
1313
import Animated from 'react-native-reanimated';
14-
import TabBarItem from './TabBarItem';
14+
import TabBarItem, { Props as TabBarItemProps } from './TabBarItem';
1515
import TabBarIndicator, { Props as IndicatorProps } from './TabBarIndicator';
1616
import memoize from './memoize';
1717
import {
@@ -49,6 +49,9 @@ export type Props<T extends Route> = SceneRendererProps & {
4949
) => React.ReactNode;
5050
renderBadge?: (scene: Scene<T>) => React.ReactNode;
5151
renderIndicator: (props: IndicatorProps<T>) => React.ReactNode;
52+
renderTabBarItem?: (
53+
props: TabBarItemProps<T> & { key: string }
54+
) => React.ReactElement;
5255
onTabPress?: (scene: Scene<T> & Event) => void;
5356
onTabLongPress?: (scene: Scene<T>) => void;
5457
tabStyle?: StyleProp<ViewStyle>;
@@ -310,6 +313,7 @@ export default class TabBar<T extends Route> extends React.Component<
310313
renderBadge,
311314
renderIcon,
312315
renderLabel,
316+
renderTabBarItem,
313317
activeColor,
314318
inactiveColor,
315319
pressColor,
@@ -400,45 +404,43 @@ export default class TabBar<T extends Route> extends React.Component<
400404
this.scrollView = el?.getNode();
401405
}}
402406
>
403-
{routes.map((route: T) => (
404-
<TabBarItem
405-
onLayout={
406-
isWidthDynamic
407-
? (e) => {
408-
this.measuredTabWidths[route.key] =
409-
e.nativeEvent.layout.width;
410-
411-
// When we have measured widths for all of the tabs, we should updates the state
412-
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
413-
if (
414-
routes.every(
415-
(r) =>
416-
typeof this.measuredTabWidths[r.key] === 'number'
417-
)
418-
) {
419-
this.setState({
420-
tabWidths: { ...this.measuredTabWidths },
421-
});
422-
}
407+
{routes.map((route: T) => {
408+
const props: TabBarItemProps<T> & { key: string } = {
409+
key: route.key,
410+
position: position,
411+
route: route,
412+
navigationState: navigationState,
413+
getAccessibilityLabel: getAccessibilityLabel,
414+
getAccessible: getAccessible,
415+
getLabelText: getLabelText,
416+
getTestID: getTestID,
417+
renderBadge: renderBadge,
418+
renderIcon: renderIcon,
419+
renderLabel: renderLabel,
420+
activeColor: activeColor,
421+
inactiveColor: inactiveColor,
422+
pressColor: pressColor,
423+
pressOpacity: pressOpacity,
424+
onLayout: isWidthDynamic
425+
? (e) => {
426+
this.measuredTabWidths[route.key] =
427+
e.nativeEvent.layout.width;
428+
429+
// When we have measured widths for all of the tabs, we should updates the state
430+
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
431+
if (
432+
routes.every(
433+
(r) =>
434+
typeof this.measuredTabWidths[r.key] === 'number'
435+
)
436+
) {
437+
this.setState({
438+
tabWidths: { ...this.measuredTabWidths },
439+
});
423440
}
424-
: undefined
425-
}
426-
key={route.key}
427-
position={position}
428-
route={route}
429-
navigationState={navigationState}
430-
getAccessibilityLabel={getAccessibilityLabel}
431-
getAccessible={getAccessible}
432-
getLabelText={getLabelText}
433-
getTestID={getTestID}
434-
renderBadge={renderBadge}
435-
renderIcon={renderIcon}
436-
renderLabel={renderLabel}
437-
activeColor={activeColor}
438-
inactiveColor={inactiveColor}
439-
pressColor={pressColor}
440-
pressOpacity={pressOpacity}
441-
onPress={() => {
441+
}
442+
: undefined,
443+
onPress: () => {
442444
const event: Scene<T> & Event = {
443445
route,
444446
defaultPrevented: false,
@@ -454,12 +456,18 @@ export default class TabBar<T extends Route> extends React.Component<
454456
}
455457

456458
this.props.jumpTo(route.key);
457-
}}
458-
onLongPress={() => onTabLongPress?.({ route })}
459-
labelStyle={labelStyle}
460-
style={tabStyle}
461-
/>
462-
))}
459+
},
460+
onLongPress: () => onTabLongPress?.({ route }),
461+
labelStyle: labelStyle,
462+
style: tabStyle,
463+
};
464+
465+
return renderTabBarItem ? (
466+
renderTabBarItem(props)
467+
) : (
468+
<TabBarItem {...props} />
469+
);
470+
})}
463471
</Animated.ScrollView>
464472
</View>
465473
</Animated.View>

src/TabBarItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import memoize from './memoize';
1515
// @ts-ignore
1616
const AnimatedInterpolate = Animated.interpolateNode || Animated.interpolate;
1717

18-
type Props<T extends Route> = {
18+
export type Props<T extends Route> = {
1919
position: Animated.Node<number>;
2020
route: T;
2121
navigationState: NavigationState<T>;

src/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ export type { Props as TabViewProps } from './TabView';
77
export { default as TabBarIndicator } from './TabBarIndicator';
88
export type { Props as TabBarIndicatorProps } from './TabBarIndicator';
99

10+
export { default as TabBarItem } from './TabBarItem';
11+
export type { Props as TabBarItemProps } from './TabBarItem';
12+
13+
export { default as TouchableItem } from './TouchableItem';
14+
1015
export { default as SceneMap } from './SceneMap';
1116
export { default as ScrollPager } from './ScrollPager';
1217

0 commit comments

Comments
 (0)