I am playing with the <ListView> component. My screen is capable of displaying 9 rows from a data set of 32. However I see in the console that the ListView component triggers the renderRow function 32 times (basically it seems to render in the background all the items of my data set).
I was expecting that the function would be triggered only when a new row appears on screen.
Is this a normal behavior?
Or is there an option that can specify under what conditions the renderRow function should be triggered?
Thanks for your suggestions.
Paul
I figured it out. In fact the rows of the list are build ahead of time so that the scroll of the list remains as smooth as possible.
The default value (in version 0.1.8) is 1000 pixels.
My list items were 20px high. 32 items * 20px = 640px. The first ten were rendered and visible anyway so there were remaining 440px to be rendered.
You can override this default setting by using the scrollRenderAheadDistance attribute of <ListView> in order to optimize your rendering if needed.
https://facebook.github.io/react-native/docs/listview.html#scrollrenderaheaddistance
Related
I am currently building an app which allows users to select their current weight and waist size. The list is long since, for example, the weight will start from 40kg up to 300kg, and each value will have a decimal point from .1 up to .9, e.g 40.0, 40.1, 40.2, 40.3, ... 40.9, 41.0, the whole numbers will be represented in a longer vertical line, while the decimal values in shorter vertical lines. So as you can imagine, the list is going to be really long. I have already implemented 2 ways: FlatList and Carousel using react-native-snap-carousel. They have their pros and cons, FlatList is much performant than the Carousel, but im having a hard time getting the value of the middle line. While the carousel performs poorly, i do have access to the current selected item. So my question here is: how do i implement this performance-wise and i have access with the currently selected item. Take Note also that i have implement FlatList's onViewableItemsChanged and it still doesn't achieve my goal
here is the screenshot of the UI:
In short:
You can check this library out: https://github.com/veizz/react-native-picker-scrollview
In detail:
There's a way to achieve this with some Flatlist props:
onScrollBeginDrag & onScrollEndDrag: detect when user starts/stops scrolling
onMomentumScrollBegin & onMomentumScrollBegin : detect scroll speed and momentum
scrollTo or scrollToIndex functions which requires Flatlist ref.
onScrollEvent if needed.
My opinion is, (which'll be my approach)
First, set the selectedItem as you like.
Then, using those scroll props above to detect which item(index) it's scrolling to. Select that item. Then scrollTo to selected.
Any point where it exceeds the threshold, use scrollTo or scrollToIndex to the next/previous item.
This is my approach, if you have your own, I'll be glad to discuss.
Happy coding!
I need to be able to animate drag and drop in my vertical list. I used vuedraggable, wrapped my list in a transition-group and it all worked sweet. Until I fetch new data from the server. Now because of the introduction of transition-group for a split second the old data and the new data live together in the DOM causing the expansion of the list and pushing subsequent div down and back up.
This is kind of expected per the docs:
the DOM operations for insertion and/or removal will be executed
immediately on next frame (Note: this is a browser animation frame,
different from Vue’s concept of nextTick).
Regardless of being able to drag and drop the element, if we were to fade in/fade out the new/old elements they will co-habitate for the time of the animation, which is not great as seen in this pen
Anyway to fade out, change the data, then fade in the new one, while maintaining the height of the list?
Note that without fade the problem is still obvious:
Pen of my issue: click the switch data button to see the issue.
Turns out it's pretty know issue. By reading through this thread and toying with this example, i was able to achieve something to my liking by using:
list-leave-active {
display: none;
}
Resulting Pen
A css fix may be to wrap the contents within a box of some height and set overflow hidden.
So, even when new elements co-exist the jump in scrollbar can be avoided.
The design of the application I am working on changes the layout based on the width of the device and there is a Flatlist component that calls scrollToIndex on the selected item so that it does not fall out side of the view when the app changes it's layout. If the last item is selected and scrolltToIndex is called, on iOS it will scroll the item all the way to the top and hide all the items above it. That makes it appear like it is the only item left and the only way to bring back the other items is to manually pull down the list. On android it works perfectly i.e it will only scroll an item high enough to fit as many items below it as possible (if more than height of container, it just scrolls it to the top).
From the FlatList>ScrollToIndex docs:
Note: Cannot scroll to locations outside the render window without specifying the getItemLayout prop.
Because FlatList is virtualized (i.e. efficient because it doesn't render the full list offscreen), it doesn't know the location of all of the elements (since they're not pre-rendered, and hence their size is unknown). It needs you to help by providing element sizes through getItemLayout to scroll beyond what's near visible. I suspect "near visible" may vary device to device with different memory settings. If you don't do this, you can end up with gaps in your list since exact placement is unknown.
So, you'll need to implement getItemLayout or use the less performant (and depricated) ListView component.
My ListView displays a feed of users, where each row is variable height (similar to Facebook).
A similar question suggests to scroll to rowIndex*rowHeight, but my rows are not the same height.
Any suggestions?
There is no simple way to do this. You can try to use onLayout event and save all rows height. But if part of rows before item you want scroll to was not rendered you can't calculate offset.
One solution in this situation is render all items at once. But there may be performance issue.
Another is scrolling bit by bit and calculate height in runtime.
My advice is redesign your UX to prevent this operation. Or use ScrollView and onLayout if row count is not too big.
UPDATED: FlatList will be added in RN 0.43. It has scrollToItem method.
Think I'm missing the obvious here, but I have a Bookstrap 3 navbar that works great in desktop view but as I squeeze the width and it gets to tablet size rather than collapsing into the toggle menu it's jumping the menu onto two lines:
http://www.doorsets.org.uk/
I've tried reducing the text size in the navbar via a media query but that isn't solving it.
What am I missing?
Appreciate it. Thank you.
NJ
One solution might be to change the point at which the navbar collapses, you can do this by creating a customized Bootstrap and setting the #grid-float-breakpoint to a larger number.
This variable unfortunately also influences the dt and dd inside a .dl-horizontal which might be a problem.
If you want to use a media query to reduce the font-size you can use the .navbar-default .navbar-nav > li > a selector. It however needs to become 9px at the smallest viewport size to still stay on a single row which is quite unreadable.
From the Bootstrap documentation:
Overflowing content
Since Bootstrap doesn't know how much space the content in your navbar needs, you might run into issues with content wrapping into a second row. To resolve this, you can:
Reduce the amount or width of navbar items.
Hide certain navbar items at certain screen sizes using responsive utility classes.
Change the point at which your navbar switches between collapsed and horizontal mode. Customize the #grid-float-breakpoint variable or add your own media query.
It goes on to say:
Changing the collapsed mobile navbar breakpoint
The navbar collapses into its vertical mobile view when the viewport is narrower than #grid-float-breakpoint, and expands into its horizontal non-mobile view when the viewport is at least #grid-float-breakpoint in width. Adjust this variable in the Less source to control when the navbar collapses/expands. The default value is 768px (the smallest "small" or "tablet" screen).