Lazy load doesn't works correctly
Current behaviour
Example: Tab1 - Tab2 - Tab3
Active tab: tab1 Target tab: tab3
When i want to go to "tab 3" by click it is rendering tab2 on the way.
Expected behaviour
Not render tab2 or what ever is between 2 tabs when sliding.
Code sample
in main file
const renderScene = ({ route }) => {
switch (route.key) {
case 'tab1':
return <Tab1 someProps />;
case 'tab2':
return <Tab2 someProps />;
case 'tab3':
return <Tab3 someProps />;
default:
return null;
}
};
also
In the tab2 i have useEffect thats how i know the tab2 renders when the screens moving
useEffect(() => {
apiSearch(query)
}, []);
Your Environment
| software | version |
|---|---|
| ios or android | android |
| react-native | 0.61.5 |
| react-native-tab-view | 2.13.0 |
| react-native-gesture-handler | 1.6.0 |
| react-native-reanimated | 1.7.1 |
| node | 10.x |
| npm or yarn | yarn,npm |
same issue
same issue @osdnk can you please verify this issue ? thank you
Hi, I solved this issue using renderPager prop like:
import {
TabView,
ScrollPager,
} from 'react-native-tab-view';
<TabView
lazy
style={{ marginTop: getStatusBarHeight() }}
navigationState={{ index, routes: routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={initialLayout}
renderTabBar={renderTabBar}
renderLazyPlaceholder={() => <Placeholder />}
renderPager={
IS_ANDROID ? undefined : (props) => <ScrollPager {...props} />
}
/>
Hi, I solved this issue using renderPager prop like:
import { TabView, ScrollPager, } from 'react-native-tab-view'; <TabView lazy style={{ marginTop: getStatusBarHeight() }} navigationState={{ index, routes: routes }} renderScene={renderScene} onIndexChange={setIndex} initialLayout={initialLayout} renderTabBar={renderTabBar} renderLazyPlaceholder={() => <Placeholder />} renderPager={ IS_ANDROID ? undefined : (props) => <ScrollPager {...props} /> } />
Only work on ios
Hi, I solved this issue using renderPager prop like:
import { TabView, ScrollPager, } from 'react-native-tab-view'; <TabView lazy style={{ marginTop: getStatusBarHeight() }} navigationState={{ index, routes: routes }} renderScene={renderScene} onIndexChange={setIndex} initialLayout={initialLayout} renderTabBar={renderTabBar} renderLazyPlaceholder={() => <Placeholder />} renderPager={ IS_ANDROID ? undefined : (props) => <ScrollPager {...props} /> } />Only work on ios
In my tests it worked on both. Below, my packages versions:
"name": "react-native-tab-view", "version": "2.14.4",
"name": "react-native", "version": "0.62.2",
Hi, I solved this issue using renderPager prop like:
import { TabView, ScrollPager, } from 'react-native-tab-view'; <TabView lazy style={{ marginTop: getStatusBarHeight() }} navigationState={{ index, routes: routes }} renderScene={renderScene} onIndexChange={setIndex} initialLayout={initialLayout} renderTabBar={renderTabBar} renderLazyPlaceholder={() => <Placeholder />} renderPager={ IS_ANDROID ? undefined : (props) => <ScrollPager {...props} /> } />Only work on ios
In my tests it worked on both. Below, my packages versions:
"name": "react-native-tab-view", "version": "2.14.4",
"name": "react-native", "version": "0.62.2",
It work perfect, but my screen using FlatList and i can't swipe to refresh (RefreshControl) when using rengerPager ScrollPager in iOS
Hi, I solved this issue using renderPager prop like:
import { TabView, ScrollPager, } from 'react-native-tab-view'; <TabView lazy style={{ marginTop: getStatusBarHeight() }} navigationState={{ index, routes: routes }} renderScene={renderScene} onIndexChange={setIndex} initialLayout={initialLayout} renderTabBar={renderTabBar} renderLazyPlaceholder={() => <Placeholder />} renderPager={ IS_ANDROID ? undefined : (props) => <ScrollPager {...props} /> } />Only work on ios
In my tests it worked on both. Below, my packages versions: "name": "react-native-tab-view", "version": "2.14.4", "name": "react-native", "version": "0.62.2",
It work perfect, but my screen using FlatList and i can't swipe to refresh (RefreshControl) when using rengerPager ScrollPager in iOS
The same here, but you can use an infinity scroll to load more items. It worked here.
Any updates here? Same issue.
Quick Fix using with React Navigation
I'm using the following hook. If it returns false, I render a placeholder instead of my screen.
import { useIsFocused } from '@react-navigation/native'
import React from 'react'
/**
* Return `true` if should be mounted. If returning `false`, you should render a placehold.
*/
export const useLazyTabScreen = (): boolean => {
const [shouldMount, setShouldMount] = React.useState(false)
const isFocused = useIsFocused()
React.useEffect(() => {
if (isFocused) {
setShouldMount(true)
}
}, [isFocused])
return shouldMount
}
i am also facing the same issue. is there any update or any solution for this?
i tried above solutions but doesn't work for me.
Hi, I'm still facing the same issue. Any solutions please? thank you
@anhquan291 I found a fix/ workaround. The issue is caused by the Pager implementation.
in the Pager code for version 2.16.0 I removed lines 595 - 613 inclusive and that solved it for me.
I paste the code I deleted below in case that helps.
onChange(
this.position,
// Listen to updates in the position to detect when we enter a screen
// This is useful for things such as lazy loading when index change will fire too late
cond(
I18nManager.isRTL
? lessThan(this.gestureX, 0)
: greaterThan(this.gestureX, 0),
// Based on the direction of the gesture, determine if we're entering the previous or next screen
cond(neq(floor(this.position), this.lastEnteredIndex), [
set(this.lastEnteredIndex, floor(this.position)),
call([floor(this.position)], this.handleEnteredIndexChange),
]),
cond(neq(ceil(this.position), this.lastEnteredIndex), [
set(this.lastEnteredIndex, ceil(this.position)),
call([ceil(this.position)], this.handleEnteredIndexChange),
])
)
),
@anhquan291 I found a fix/ workaround. The issue is caused by the Pager implementation.
in the Pager code for version 2.16.0 I removed lines 595 - 613 inclusive and that solved it for me.
I paste the code I deleted below in case that helps.
onChange( this.position, // Listen to updates in the position to detect when we enter a screen // This is useful for things such as lazy loading when index change will fire too late cond( I18nManager.isRTL ? lessThan(this.gestureX, 0) : greaterThan(this.gestureX, 0), // Based on the direction of the gesture, determine if we're entering the previous or next screen cond(neq(floor(this.position), this.lastEnteredIndex), [ set(this.lastEnteredIndex, floor(this.position)), call([floor(this.position)], this.handleEnteredIndexChange), ]), cond(neq(ceil(this.position), this.lastEnteredIndex), [ set(this.lastEnteredIndex, ceil(this.position)), call([ceil(this.position)], this.handleEnteredIndexChange), ]) ) ),
Thank you @seanowenhayes. I'm gonna try it now.
Lazy load does not work correctly on android and ios. In web it will display the lazy placeholder when loading the scene. On android it loaded all scenes in one go.
Same problem here. Did anyone find a solution?
Hey, this was solved here #1392 and released in 3.3.0