Material Top Tabs is very unstable when screens contains lists inside
Current behavior
Hi, I am using Material Top Tabs v 6.6.14, i have a dynamic tab navigator that can contain as much tabs as possible, where the lists item contains separate graphs. I am also hiding tabs label and updating the title of the screen when a tab is swiped. The first problem is when i swipe the tab, the screen title update is very slow. I checked the focus event in the listener where i wanted to update the tab title but the focus event inside listeners is being called after some delay. Also when i quickly swipe between tabs, the tabs start weird behavior and jumping between every tab infinitely. Can someone please help on this, i have spent so much time on this and couldn't find a way to solve.
This is my dynamic tab navigator
`import React, { useEffect, useState } from 'react';
import { Dimensions, StyleSheet, Text, View } from 'react-native'
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import { getFocusedRouteNameFromRoute, useNavigation } from '@react-navigation/native';
import WidgetsContainer from './WidgetsContainer';
import { useSelector } from 'react-redux';
import TextWrapper from './TextWrapper';
import LoaderKit from 'react-native-loader-kit';
import { colorStyles } from '../css/AppStyles';
const Tab = createMaterialTopTabNavigator();
const UserTabs = (props) => {
//console.log("props", props);
const navigation = useNavigation();
const { setFocusedTabDetails, parentNavigation, removeItem } = props;
const tabsAndWidgets = useSelector((state) => state.userTabsAndWidgetsReducer.userTabsAndWidgets);
const getHeaderTitle = (route) => {
console.log("route", route);
// If the focused route is not found, we need to assume it's the initial screen
// This can happen during if there hasn't been any navigation inside the screen
// In our case, it's "Feed" as that's the first screen inside the navigator
//const routeName = getFocusedRouteNameFromRoute(route);
//console.log("routeName", routeName);
return route.name;
}
return (
<Tab.Navigator
initialRouteName={'Home'}
screenOptions={{
tabBarStyle: { display: "none" },
lazy: true,
lazyPlaceholder: () =>
<View style={styles.lazyPlaceHolderStyle}>
<LoaderKit
style={styles.loaderStyle}
name={'BallSpinFadeLoader'}
color={colorStyles.headerColor}
/>
<TextWrapper style={{color: colorStyles.headerColor}}>Loading...\nPlease wait</TextWrapper>
</View>
}}>
{
tabsAndWidgets?.map((tab, index) =>
<Tab.Screen
key={index}
name={tab?.tabName}
listeners={{
blur: (e) => {
//console.log("tab blurred");
},
tabPress: e => console.log('Tab press', e.target),
focus: (e) => {
//parentNavigation.setParams({ showDeleteButton: tab.systemTab ? false : true });
//parentNavigation.setOptions({ headerTitle: tab.tabName });
//setFocusedTabDetails({ tabID: tab.tabID, "tabName": tab.tabName, "tabIndex": index, "systemTab": tab.systemTab });
//console.log('Tab focus', e)
},
swipeStart: (e) => {
//console.log("swipe start called", e);
},
swipeEnd: (e) => {
//console.log("swipe end called", e);
},
}}
>
{ props =>
<WidgetsContainer
{...props}
extraParams = {{
"tabDetails": tab,
"tabIndex": index,
"parentNavigation": parentNavigation,
"setFocusedTabDetails": setFocusedTabDetails,
"removeItem": removeItem
}}
/>
}
</Tab.Screen>
)
}
</Tab.Navigator>
);
}
const styles = StyleSheet.create({
lazyPlaceHolderStyle: {
flex: 1,
flexDirection: "row",
justifyContent: "center",
alignItems: "center"
},
loaderStyle: {
width: 40,
height: 40,
marginHorizontal: 10
},
});
export default UserTabs;`and this is the code where i update the screen title inside useEffect function
`const isFocused = useIsFocused();
useEffect(() => {
console.log("isFocused");
if (isFocused) {
// console.log("extraparams", extraParams.tabDetails);
const tab = extraParams.tabDetails;
const tabIndex = extraParams.tabIndex;
extraParams.setFocusedTabDetails({ tabID: tab.tabID, "tabName": tab.tabName, "tabIndex": tabIndex, "systemTab": tab.systemTab });
//setLoading({load: true, loadingText: "Populating Widgets...\nPlease wait."});
//setTimeout(() => setLoading({load: false, loadingText: ""}), 2000);
//navigation.setOptions({ swipeEnabled: false });
//setTimeout(() => navigation.setOptions({ swipeEnabled: true }), 2000);
}
}, [isFocused]);`The title update and tabs jumping becomes much worse when more tabs are added. Also is there a way that we can know when a tab is fully rendered so until then we can atleast limit the user from quickly swiping back and forth? Please advise. Thanks.
Expected behavior
The tabs should behave fast and responsive when swiped
Reproduction
not available
Platform
- Android
- iOS
- Web
- Windows
- MacOS
Packages
- @react-navigation/drawer
- @react-navigation/material-top-tabs
- @react-navigation/stack
- @react-navigation/native-stack
Environment
| package | version |
|---|---|
| @react-navigation/native | 6.1.18 |
| @react-navigation/drawer | 6.7.2 |
| @react-navigation/material-top-tabs | 6.6.14 |
| @react-navigation/stack | 6.4.1 |
| react-native-screens | 3.29.0 |
| react-native-safe-area-context | 4.10.8 |
| react-native-gesture-handler | 2.18.0 |
| react-native-reanimated | 3.14.0 |
| react-native-pager-view | 6.4.1 |
| react-native | 0.74.5 |
Source: react-navigation/react-navigation