I am currently using the ViewPagerAndroid component to do a matching/unmatching function which requires dynamic data updating in the source data of the component. The children of of the view pager is generated by a function makeItems(this.state.data) and it returns an array of keyed views. i.e. [< View key={1}/>, < View key={2}/>....] with the index being the index of the for loop that generates the array from the source data. The views contain composite views of touchable highlight but all are wrapped by a view container. I kept the data in the state of the component and whenever data updates I call setState and ViewPagerAndroid.setPage(0). The data update works fine when I reduce the data (splice) but returns an empty view for the new data when I add new data to the array. The data before the update was displayed properly.I have checked my makeItems() function that the updated data has been passed in proper.
< ViewPagerAndroid
name = 'Page Viewer 1'
style = {styles.matchingPanelViewPager}
initialPage={this.state.currentPage}
onPageSelected = {(e)=>{
console.log(e.nativeEvent.position);
}}
ref = {viewPager =>{this.viewPager = viewPager;}}>
{ this.makeItems(this.state.data) }
</ ViewPagerAndroid>
I am using RN0.16.0 on Mac OS X, Genymotion, Android 4.2.2.
Same issue raised in StackOverflow: http://stackoverflow.com/questions/34279503/viewpagerandroid-returns-empty-view-when-new-source-data-added
Thanks a lot for your help!
Hey ACCTFORGH, thanks for reporting this issue!
React Native, as you've probably heard, is getting really popular and truth is we're getting a bit overwhelmed by the activity surrounding it. There are just too many issues for us to manage properly.
react-native or for more real time interactions, ask on Discord in the #react-native channel.Hi.
I'm facing the same issue.
I have a pager that renders an array of views.
When I deleted an entry of the array, the next render of the pager is drawing an empty view.
Also, the last view of the array goes out of screen bounds and cant be reached.
I dont really know where I have to start looking to fully realize whats really happen
Regards
I ran into this too and my temporary solution was to give it a key, then change that key every time you update the data source. A PR is welcome to fix this!
I used this third party component and it works well with data updates. The syntax is more elegant too.
Having the same issue (actually adding is ok, but slicing array of pages, and pushing causes this).
I've tried changing key (to AndroidViewPager) according to @brentvatne proposal, but then other problems occurred - no animation sometimes, and after some fast changes errors spawned.
I know there are problems with the native android component (look here), so maybe the solution should start there.
But actually the best solution (for my desires) will be to add pagingEnabled to ScrollView in android, and than even deprecate AndroidViewPager.
BTW, Iv'e tried the third party solution @ACCTFORGH suggested, but it's really low performant.
any solution? same here. update data but return a empty view
In my scenario I'm either appending a page or slicing and then appending to the sliced pages array,
What currently works for me is adding key based on time on this condition:
androidViewPagerKey = newPages.length < pages.length ? Date.now() : androidViewPagerKey
return <ViewPagerAndroid
key={androidViewPagerKey}...
any solution?
@Richard-Cao, this works for me <ViewPagerAndroid key={pageCount}....
Thanks a lot @yonatanmn
Thx, I wil try. @thrap
Having the same issue. Using a new key for the ViewPagerAndroid Component solves this for now, but it is not an efficient solution, when only certain pages of the ViewPager should be replaced.
Faced the same issue, and there is a fix for this.
Actually the implementation of ReactViewPager.java is incomplete.
Following method should be implemented also:
@Override
public int getItemPosition(Object object) {
int index = mViews.indexOf(object);
if (index >= 0) return index;
return PagerAdapter.POSITION_NONE;
}
Next, following method also should be fixed:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
In my case, I copied com.facebook.react.views.viewpager classes to my project, fixed it and exported it as my own native view using same name. Now ViewPagerAndroid pages are properly created and destroyed reflecting changes of children array
Hi there! This issue is being closed because it has been inactive for a while.
But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/viewpagerandroid-returns-empty-view-when-new-source-data-added
Product Pains has been very useful in highlighting the top bugs and feature requests:
https://productpains.com/product/react-native?tab=top
Also, if this issue is a bug, please consider sending a pull request with a fix.
@kvj Do you want to send a PR adding those methods?
+1 for a fix. I think it's important because we can't have infinite viewpagers otherwise in Android.
its def. still a problem version: 0.44.3 yonatanmn's solution with setting a key = current timestamp on the viewPager itself fixes. its fine for now. or till 2038 :)
Adding a dynamic key fixes the problem. But if I do i.e. key={pages.length} (so the key changes whenever the number of children changes) I experience a flickering behaviour if the key changes.
Have you tried the virtualizedList with pagingenabled?
On iOS that works perfect for an infinite viewpager.
The problem is specifically related to android.
I know but maybe is ViewPagerAndroid not the way to go. I have an infinite viewpager made with VirtualizedList. I'm sure you'll need some customizing
import React, { Component } from 'react'
import { View, Text, Dimensions, VirtualizedList } from 'react-native'
const { width, height } = Dimensions.get('window')
const startAtIndex = 5000
const stupidList = new Array(startAtIndex * 2)
class InfiniteViewPager extends Component {
//only use if you want current page
_onScrollEnd(e) {
// const contentOffset = e.nativeEvent.contentOffset
// const viewSize = e.nativeEvent.layoutMeasurement
// // Divide the horizontal offset by the width of the view to see which page is visible
// const pageNum = Math.floor(contentOffset.x / viewSize.width)
}
_renderPage(info) {
const { index } = info
return (
<View style={{ width, height }}>
<Text>
{' '}{`index:${index}`}{' '}
</Text>
</View>
)
}
render() {
return (
<VirtualizedList
horizontal
pagingEnabled
initialNumToRender={3}
getItemCount={data => data.length}
data={stupidList}
initialScrollIndex={startAtIndex}
keyExtractor={(item, index) => index}
getItemLayout={(data, index) => ({
length: width,
offset: width * index,
index,
})}
maxToRenderPerBatch={1}
windowSize={1}
getItem={(data, index) => ({ index })}
renderItem={this._renderPage}
onMomentumScrollEnd={this._onScrollEnd}
/>
)
}
}
Most helpful comment
@Richard-Cao, this works for me
<ViewPagerAndroid key={pageCount}....Thanks a lot @yonatanmn