I have 4 screens in bottom navigation. The first screen consists of a map with the timer of 10s. As soon as the timer get executed the api is hit.
But when a user switch the screen with bottom navigation tab item. The timer still works in background and due to which the other api start having lag.
How to make sure the timer only works when that screen is focused?
I tried updating the name of screen user is navigating using useContext however when the timer execute it do not return the update name of the screen. every time it returns the older screen name.
This code is in all the 4 bottom navigation screens. As I have observed useEffect only works once. and whenever user clicks it second time this hook do not get trigger.
HOME SCREEN
const {activeScreenFun, activeScreen, previousScreen} = useNavigationCustom();
React.useEffect(() => {
const unsubscribe = navigation.addListener('tabPress', e => {
activeScreenFun('Home');
});
return unsubscribe;
}, [navigation]);
useEffect(() => {
activeScreenFun('Home');
}, []);
Timer
useEffect(() => {
if (timer) {
let interval = setInterval(() => {
getAPiData();
}, 10000);
return () => {
clearInterval(interval);
};
}
}, [timer]);
NavigationCustomProvider Context
export function NavigationCustomProvider({children}) {
const [activeScreen, setActiveScreen] = useState('');
const [previousScreen, setPreviousScreen] = useState('');
const activeScreenFun = useCallback(async function (activeScreenSelected) {
setPreviousScreen(activeScreen);
setActiveScreen(activeScreenSelected);
});
const getActiveScreenFun = useCallback(() => {
return activeScreen;
});
Bottom Navigation Code
export default function MainScreen() {
return (
<NavigationCustomProvider>
<MainLayout>
<MainLayoutScreen
name={HOME_ROUTE}
icon={TrackItIcon}
activeIcon={TrackItActiveIcon}
component={HomeScreen}
/>
<MainLayoutScreen
name={ATTENDACE_ROUTE}
icon={AttendanceIcon}
activeIcon={AttendanceActiveIcon}
component={AttendanceScreen}
/>
<MainLayoutScreen
name={NOTIFICATION_ROUTE}
icon={NotificationIcon}
activeIcon={NotificationActiveIcon}
component={NotificationScreen}
/>
<MainLayoutScreen
name={MY_ACCOUNT_ROUTE}
icon={AccountIcon}
activeIcon={AccountActiveIcon}
component={ProfileScreen}
/>
</MainLayout>
</NavigationCustomProvider>
);
}
TAB BAR CODE
routes = children.map(x => ({
name: x.props.name,
icon: x.props.icon,
activeIcon: x.props.activeIcon,
component: x.props.component,
}));
<Tab.Navigator
barStyle={{backgroundColor: theme.colors.white}}
activeColor={theme.colors.primary}
shifting={true}
labeled={true}>
{routes.map(x => {
let Icon = x.icon;
let ActiveIcon = x.activeIcon;
return (
<Tab.Screen
key={x.name}
name={x.name}
component={x.component}
options={{
tabBrColor: theme.colors.white,
tabBarIcon: ({focused}) =>
focused ? <ActiveIcon /> : <Icon />,
}}
/>
);
})}
</Tab.Navigator>
A new timer instance is created for each new component rerender.
Even if you clear an instance of the timer when the component unmounts, previously created instances are still running in the background.
you need to persist a single instance of timer across all component rerender cycles.
React provide hook useRef
to persist value for all component render cycle.
let interval = React.useRef(null);
useEffect(() => {
if (timer) {
// Assign and persist Timer value with ref
interval.current = setInterval(() => {
getAPiData();
}, 10000);
return () => {
if (interval.current) {
clearInterval(interval);
}
};
}
}, [timer]);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.