When the data used to generate children for <ViewPager /> is initially empty ([]), subsequent render passes with actual non-empty lists of data do create the correct children/pages: No ViewPager pages content is rendered at all.
ViewPager should correctly render its children. Previous (e.g. empty) children states should not affect the rendering behaviour.
react-native info output:
System:
OS: macOS 10.15.5
CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
Memory: 500.04 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
Yarn: 1.17.3 - ~/.yarn/bin/yarn
npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
Android SDK:
API Levels: 23, 27, 28
Build Tools: 27.0.3, 28.0.1, 28.0.3
Android NDK: Not Found
IDEs:
Android Studio: 3.1 AI-173.4819257
Xcode: 11.5/11E608c - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_201 - /usr/bin/javac
Python: 3.7.6 - /opt/anaconda3/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: ~16.11.0 => 16.11.0
react-native: https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz => 0.62.2
npmGlobalPackages:
*react-native*: Not Found
Library version: 3.3.0, 4.1.6
_This behavior has been reproduced on iPhone X and the iOS simulator (both running iOS 13.5.1)._
<ViewPager /> to your view hierarchyArray.map()) from dynamic dataViewPager, e.g. fetch data from remote web service=> Non-empty data should be rendered correctly, but is not.
import * as React from 'react'
import { useEffect, useState } from 'react'
import { Text, View } from 'react-native'
import ViewPager from '@react-native-community/viewpager'
export const BugReproductionContext = () => {
// Observation: Initializing with a non-empty array will prevent the bug
const [items, setItems] = useState<string[]>([])
useEffect(() => {
setTimeout(() => {
setItems(['one', 'two', 'three'])
}, 1000)
}, [setItems])
// Workaround: prevent empty ViewPager initialization
// if (!items.length) {
// return null
// }
return (
<ViewPager
style={{ width: '100%', height: 50, backgroundColor: '#ddd' }}
initialPage={0}
>
{/*<View key="-1">*/}
{/* <Text>A static item which is always rendered. Adding it will also prevent the bug. </Text>*/}
{/*</View>*/}
{items.map((item, index) => (
<View key={index}>
<Text>Item: {item}</Text>
</View>
))}
</ViewPager>
)
}
Hey @stefan-girlich
I was trying to reproduce your issue on real device (Samsung):
https://github.com/react-native-community/react-native-viewpager/tree/219
But it looks like everything work fine.
Hi @troZee , thanks for double-checking.
Would you happen to have an iOS device available? I could imagine that this could be related to the native layout mechanisms.
I thought, it was related to android platform.
I have not got any change to check it on real iOS device. I will try to do it as fast as I can.
Maybe we can consider to return empty view, when children array is empty ? WDYT ?
Same Problem, I have opened almost the same problem on android 5.0 and 5.0.2 API 21.
To see the problem once test with a FlatList or A heavy Component within viewpager pages. and also render them condtionally. Please be inform this problems is only for the first renders, as it gets render but nothing get displayed everything is blank page. but when I call page.setPage function everything is Fine
const MainComponent = ()=> {
return (
<>
<ViewPager initialPage={0} ref={page} style={{ flex: 1 }} scrollEnabled={false}>
<View key="1">
<FlatList
style={{ flex: 1 }} data={contacts} keyExtractor={_keyExtractor}
getItemLayout={getItemLayout} renderItem={renderItem}
/>
</View>
<View key="2">
<MyContacts /> // the component also contains flatlist
</View>
<View key="3">
<Profile /> // this is also still heavy
</View>
</ViewPager>
{renderTabRouter}
{renderModal}
</>
);
}
const App = ()=> {
if(registered === true) return <MainComponent />
else return <RegisteredComponent>
}
@muhammadwafa page.setPage() does not fix it on android 8.
Only if touch, it gets rendered.
Hey @stefan-girlich
I was trying to reproduce your issue on real device (Samsung):
https://github.com/react-native-community/react-native-viewpager/tree/219But it looks like everything work fine.
Actually, I have the same issue on ios first array is empty then after API call we set the state but noting show on the screen
same issue on iOS here, I solved it by making the key of the PagerView dependent on whether the dataset is empty.
const dataIsEmpty = !data?.length
...
<PagerView
key={String(dataIsEmpty)}
...
/>
Hey @stefan-girlich
I was trying to reproduce your issue on real device (Samsung):
https://github.com/react-native-community/react-native-viewpager/tree/219
But it looks like everything work fine.Actually, I have the same issue on ios first array is empty then after API call we set the state but noting show on the screen
I had exactly the same issue and what i concluded is that the array should not be empty at start when ViewPager is rendered.
So you can add a check if array is empty then just rendered an empty View.
E.g Inside ViewPager
<ViewPager props>
{array.length<1 && <View key = "SomeKey"/>}
{array.map(item => <SomeComponent props />)}
</ViewPager>
Most helpful comment
Actually, I have the same issue on ios first array is empty then after API call we set the state but noting show on the screen