ReactNative render nested list slow: Suggestion - react-native

JSON Structure:
sectionItems={key: ..., name: .., title: ..listOf 20 nested data }
data =
{
"sections": [...sectionItems of 50 items]
}
When displaying in the FlatList its rendering too slow,
<FlatList
renderItem={({item}) => <Section item={item} />}
initialNumToRender={lastSelectedItemIndex}
/>
Prior to FlatList have used SectionList to render the data but it was too slow to render the data, the requirement is to show all the content in one shot, but FlatList takes too much time to load the items in the viewport, showing more whitespace.
What can be best solution the render a nested list, SectionList or FlatList, the list should have selected item highlighted, so i need to connect to store too.

I just do this by nesting flat lists and taking care of proper rendering within list items. For example I had a list of days, and per each day there were 'entries'. Instead of section list I have a flat list which holds "days list". The day list displays the list header for new day, say 14th January. the rest of this list item is a flat list, containing all the entries for this list. You can highlight easily by making the specific list item wrapped in a touchable. I must render 1000 elements at time and have never had performance issues besides massive updates coming after syncing process. I think this approach might work best for you.

Related

Are there some components to replace Flatlist in React Native for better performance

My problem is I'm using Flatlist component to render items that are not pure components. they have a bunch of states, hooks, and many functions to handle logic. Moreover, my list also has many items, at least 28 items because I want to render some information in a month. the number of items may be bigger when I fetch more data for other months.
As a result, my app's performance is really slow. Are there any solutions out there?
I think you have to use pagination to increase the performance. If you want the best possible performance with Flatlist you should do pre and post pagination. Like you have to add and remove equal amount of items from data array passed to Flatlist simultaneously.
i.e
let suppose you want to maintain the 50 items count in the array.
const [data,setData]=useState([])
const useEffect(()=>{
//fetch initial 50 items from api
setData([...50item...])
},[])
//when scrolling down the Flatlist
onFlatlistScrollDownEndReached = ()=>{
//fetch let suppose 10 more post items from api page# wise
let prevData= data.splice(10,data.length) //remove first 10 items
let new10Items = [...10 fetched from api...]
setData([...prevData,... new10Items])
}
//when scrolling up the Flatlist
onFlatlistScrollUpEndReached = ()=>{
//fetch let suppose 10 pre items from api page# wise
let prevData= data.splice(data.length-10,data.length) //remove last 10 items
let new10Items = [...10 fetched from api...]
setData([... new10Items,... prevData])
}
Try these alternatives
FlashList : Fast & Performant React Native List by Shopify
FlashList Documentation
RecyclerListView : High performance ListView for React Native and Web by Flipkart
Medium Documentation

Deselect v-list-item when changing its value

I have a v-list-item-group with some v-list-item's inside with an associated value. The problem is that when I change the value of the selected v-list-item it doesn't react. I want it to be selected only when the new value matches the v-list-item-group's model and be unselected otherwise. What is the best way to achieve such a behaviour?
Example. When you edit the list item value, for example, by changing the lower left field from "Bluetooth" to "Bluetooth1", I want the list item to get deselected automatically because its value isn't longer matching v-list-item-group's model ("Bluetooth1" != "Bluetooth"). And when you change it back to "Bluetooth" I want it to get selected again.
The one on the right modifies the v-list-item-group's model and this works as expected.
My actual use case is rendering lists of thousands of elements quickly without rendering them all. To achieve it I use a recycle-scroller component inside my v-list-item-group to manage its items. It creates a few dozens of v-list-items and as user scrolls it reuses them by moving them around and replacing their value, icon and text with corresponding data from my array. The problem is that when user selects some list item then scrolls the list, the selected item gets reused. Despite the fact that it now has a different value, text and icon it still looks as selected. So they see it as if some different item was selected.
I hope this works for you:
<v-list-item-group v-model="model" :color="color">
// other html
Then add a computed property:
computed: {
color(){
if (this.model == this.items[1].text) {
return 'indigo'
} else {
return 'black'
}
}
}

How to find all visible deeply nested ListView items?

Im working on a squish based test and try to get decent (visible) items from a QML ListView that are deeply nested that i just can't pick due to its dynamic behavior
I've get the list itself by using waitForObject with a object map name
There are several nested items in the list an i want to get all occurrences of the MyTypeCCC_QMLTYPE_72 when property visible is true
I've dumped my current class/property child-hierachy:
MyTypeAAA_QMLTYPE_195
children[0] QQuickItem
children[0] QQuickColumn
children[0] MyTypeBBB_QMLTYPE_189
children[0] MyTypeCCC_QMLTYPE_7 visible(true)
I've found this in the Squish-KB: https://kb.froglogic.com/display/KB/Example+-+Finding+child+objects+by+type+and+property+values
so i can write my own search code traversing the tree etc. but i think that could(should) be an easier solution?
can i rely on the exact hierarchy? (but what i the UI design changed another time)
i could maybe add ids to the MyTypeCCC_... if that helps
I've got several of this list with different types/nesting and i hope to find a easy solution that works for all/many of the case
any ideas?
ListView is a subclass of Flickable and all its delegates are immediate children of ContentItem, you can safely iterate over its children to get all list items, but be aware that not all of its children are list delegates, so you have to filter them, e.g. by type. To find nested elements just search for them inside list item, i.e. use list item as a container. To create container locator you can use its coordinates (these are coordinates within the list, so they will be unique). Code may look like this:
list_view = findObject(list_locator)
nested = []
for i in range(list_view.contentItem.children.count):
item = list_view.contentItem.children.at(i)
if className(item) == 'MyTypeAAA':
netsed.append(findObject({'container': {'x': item.x, 'y': item.y, 'type': className(item)}, 'type': 'MyTypeCCC'}))

React Native: Z Index on selection

There have been a lot of posts regarding z index and layer ordering but none with much of a solution. Its easy enough to layer things as you need, but if you need dynamic layer re-ordering it becomes a problem. Like for example I have four moveable elements, when one is selected it should move above the others but they are already in set order so each moves under the other.
If they are layered in render order than how can the active item move to the front and move above the other three?
You may solve this by changing the rendering order of your components. Lets say you have some items you want to render in an array and an index of the selected item, so your render method may look like this:
render() {
const items = ....;
const selectedIndex = ...;
return (
<View>
{items.filter((item, index) => index != selectedIndex)}
{items[selectedIndex]}
</View>
);
}
This way your selected item would always render last and be on top of the others.

Use Dojo Drag and Drop together with Dojo Moveable

I'm using Dojo.dnd to transfer items between to areas. The problem is: the items will snap into place once I drop them, but I'd like to have them stay where I drop them, but only for one area.
Here's a little code to explain this better:
<div id="dropZone" class="dropZone">
<div id="itemNodes"></div>
<div id="targetZone" dojoType="dojo.dnd.Source"></div>
</div>
"dropZone" is a DIV that contains two dojo.dnd.Source-areas, "itemNodes" (created programmatically) and "targetZone". Items (DIVs with images) should be dragged from a simple list out of "itemNodes" into "targetZone" and stay where they are dropped. As soon as they are dragged out of "targetZone" they should snap back to the list inside "itemNodes".
Here's the code I use to create the items:
var nodelist = new dojo.dnd.Source("itemNodes");
{Smarty-Loop}
nodelist.insertNodes(false, ['<img class="dragItem" src="{$items->info.itemtext}" alt="{$items->info.itemtext}" border="0" />']);
{/Smarty-Loop}
But this way I just have two lists of items, the items dropped into "targetZone" won't stay where I dropped them. I've tried a loop dojo.query(".dojoDndItem").forEach(function(node) to grab all items and change them to a "moveable"-type:
using dojo.dnd.move.constrainedMoveable will change the items so they can always be moved around (even in "itemNodes")
using dojo.dnd.move.boxConstrainedMoveable and defining the "box" to the borders of "targetZone" makes it possible to just move the items around inside "targetZone", but as soon as I drop them, I can't grab and move them back out. (Strange: dojo.connect(node, "onMoved" doesn't work here, the even won't fire, no matter what.)
So here's the question: is it possible to create two dnd.Sources where I can move items back and forth and let the items be "moveable" only in one of the sources?Or is there a workaround like making the items moveable and if they're not dropped into "targetZone" they'll be moved back to the list in "itemNodes" automatically?
Once the page is submitted, I have to save the position of every item that has been placed into "targetZone". (The next step will be positioning the items inside "targetZone" on page load if the grid has already been filled before, but I'd be happy to just get the thing working in the first place.)
Any hint is appreciated.
Greetings, Select0r
There is no direct support for such features. It can be done with a custom code, e.g., by subclassing a Source and overriding its insertNodes().
Here's a quick workaround to get this working:
I ended up using only one DIV which is a dojo.dnd.Source and contains the items that should be dropped into a "dropZone" and moved around in it while snapping back to the item-list when placed outside the dropZone.
All items are a dojo.dnd.move.parentConstrainedMoveable to make them movable in the originating DIV. Connecting to onMoveStop will give me the opportunity to decide whether the "drop" has occured in the dropZone or somewhere else.
if (coordX >= (dropCoords.l + dropAreaX) &&
coordX <= (dropCoords.l + dropAreaX + dropAreaW) &&
coordY >= (dropCoords.t + dropAreaY) &&
coordY <= (dropCoords.t + dropAreaY + dropAreaH))
{
// OK!
}
else
{
// outside, snap back to list
}
dropAreaX and dropAreaY contain the coordinates where the dropZone starts, dropAreaW and dropAreaH contain its width and height.
If "OK!", the items will be saved into an array, so I know which items have been dropped. Otherwise the item will be removed from that array (if it's in there) and the item will be placed back into the list (via CSS "left: 0"). The number of elements in the array will tell me how many elements are left in the list, so I can "stack" them in a loop using "top: numberOfElement * heightOfElement px").
There's more to it as I need the items coordinates written to hidden fields, but I guess this should get anybody who's working on a similar problem on the right track.