React-native-pager-view: Pages are not rendered when first render pass involves empty data set

Created on 18 Aug 2020  路  9Comments  路  Source: callstack/react-native-pager-view

Bug report

Summary

Current behavior

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.

Expected behaviour

ViewPager should correctly render its children. Previous (e.g. empty) children states should not affect the rendering behaviour.

Environment info

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)._

Steps to reproduce

  1. Add <ViewPager /> to your view hierarchy
  2. Add custom child/page elements generated (e.g. via Array.map()) from dynamic data
  3. Define data/children to be initially empty
  4. Initialize data to display in ViewPager, e.g. fetch data from remote web service

=> Non-empty data should be rendered correctly, but is not.

Reproducible sample code

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>
    )
}

ios

Most helpful comment

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

All 9 comments

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/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

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>

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thecodecafe picture thecodecafe  路  4Comments

ferrannp picture ferrannp  路  8Comments

troZee picture troZee  路  3Comments

ferrannp picture ferrannp  路  4Comments

ivan3177 picture ivan3177  路  6Comments