React Native List performance - performance

I have a FlatList inside of a Modal in my application the Flatlist is filled with ListItem components from 'react-native-elements'.
The ListItems just have a title and an onPress method and nothing else, but the list has 250-300 items. The list is very laggy. I understand that is going to happen with a lot of items, but with the list I cant scroll to the bottom immediately. I can scroll a certain distance then it loads up the next few items then scroll a bit more then load a bit etc. This makes picking an item lower on the list or at the bottom incredibly slow.
My data is an array of { imgnames: "imglink" } objects and the list is sorted alphabetically.
I was wondering if this performance issue is going to happen no matter what because of the amount of items, or if its because it is inside of the module.
I just want to be able to scroll the entire length of the list immediately, so I can scroll to the 'M' or 'P' sections straightaway and then have a small delay while the list renders.
What would be the best list implementation for this.
FlatList Code:
<FlatList
data={this.props.list}
renderItem={
({item}) => <ListItem hideChevron = {true} onPress={() => this._setImage(item.imgLink)} title={item.key} removeClippedSubviews = {true} initialNumToRender={5}/>
}/>

Setting initailRenderNum and removeClipping props should help with the performance problems of the FlatList.
Example:
<FlatList
data={this.props.list}
removeClippedSubviews={true}
initialNumToRender={5}
renderItem={
({item}) => <ListItem hideChevron={true} onPress={() => this._setImage(item.imgLink)} title={item.key} />
}/>

Related

Scroll one page to the right in Cypress

How could I scroll one page to the right in Cypress?
E.g. I have a horizontally scrollable area. The area contains elements a, b and if I scroll to the right a and b get destroyed, while c and d get added.
My attempt is to find out the width of the scrollable view and then scroll that amount to the right. But the width does not get retrieved before the scrollTo gets called.
Here is what I am trying to do:
const width = cy.getCy("scroll-viewport").invoke("width");
cy.getCy("scroll-viewport").scrollTo(width, 0);
Your code sample has some mystery about it, for example what is cy.getCy().
I can show you how to do it with standard code, and you can adapt from there.
Assuming scroll-viewport is a selector for the scroll container (the owner of the scroll bar)
cy.get("scroll-viewport").then($scrollContainer => {
const width = $scrollContainer[0].offsetWidth;
$scrollContainer[0].scrollTo(width, 0);
})
Note $scrollContainer[0].scrollWidth gives you the total width after scrolling, in case you need that.

How to display bars from left to right with a fixed bar gap?

I want to display bars from left to right with a fixed bar gap, rather than display them evenly.
I have tried to add barCategoryGap or barGap prop with fixed number, but no influence for the chart like this:
And my code is:
<BarChart data={data} barSize={10} barCategoryGap={1}>
<YAxis
...some props
/>
<Tooltip />
<Bar dataKey="responseTime">
{data.map((item, index) => (
<Cell fill={item.isPass ? '#3c763d' : '#a94442'} key={index} />
))}
</Bar>
</BarChart>
In your graph, you don't have any XAxis specified to group your bars into categories. Because of this, the props barGap and barCategoryGap won't work, since there is no category to make changes on.
To solve your problem, you should add the missing XAxis which datakey would be a prop in your data object array, that shares the same object where your Bars values come from so that they can be regrouped. Afterwards you can "play" around with the gap between the different bars, just like a demo found on Recharts for Bars.

Have a draggable item in jsPlumb which is made of multiple items

I'd like to create a single draggable item in jsPlumb which is actually composed of multiple items: a "main item" which has an anchor which is a connection target (isTarget: true), and multiple "sub items" which display stacked up, each of which has an anchor which is a connection source. Something like this:
Subthings should always be presented in the way above; they aren't draggable around inside the item, nor are they draggable to other items. Dragging anywhere on the main item or any subitem drags the whole group around from place to place.
Am I best to model this as separate things in a jsPlumb.Group, or is this really all just one "wrapper" div with many divs inside it? If it's the latter, how do I add anchors to the main and subitems within the wrapper, if it's the wrapper that I tell jsPlumb about?
As far as I can tell, this Just Works.
const a = document.createElement("article");
const d = document.createElement("div");
const p = document.createElement("p");
a.appendChild(d);
a.appendChild(p);
pane.appendChild(a);
jsPlumb.draggable(a);
var endpoint1 = jsPlumb.addEndpoint(d, { isTarget:true, anchors: ["Top"] });
var endpoint2 = jsPlumb.addEndpoint(p, { isSource:true, anchors: ["Right"] });
Create a "wrapper" (here a, an article), and mark it draggable; append subitems to it, and add Endpoints to them; everything works. Done.

Vue.js call transition explicitly

I know the typical way for doing animations in Vue.js, adding the transition="my-animation" on the HTML element.
I'm wondering if can I call explicitly that animation form code and not just depending on v-show / v-if.
I'd like to "shake" a component (A) each time another one (B) is clicked. For that I use a pulse transition (from animated.css).
For the moment B dispatches a message each time is clicked.
A receives the message and sets it's property animate to true. Then A shakes thanks to, in the HTML:
<div id="A" class="animated"
transition="pulse"
v-show="show"
v-bind:class="{ 'pulse': animate }"
>
Onces it's being animated, won't do it anymore, since A's animateprop is already set to true. I'd need to reset it to false so on next click the component could shake again.
I've tried with the transition hooks:
Vue.transition('pulse', {
afterLeave: function (el) {
this.animate = false;
},
})
It won't animate (shake) again since the element already has the class. You need to remove it first.
There are probably a couple of ways to accomplish this, using setTimeout to set animate to false is a very easy approach.
Using Vue's class binding (ex. :class="{'bounce animated': animated}"), run the animation by setting the animated property to true, then remove the class the animation by setting it back to false after the amount of time it takes to finish.
Here is a fiddle with exactly what you want to do, using setTimeout to set animate back to false after a 1s animation.
https://jsfiddle.net/crabbly/xcLrbtzj/

Finding Out Which Elements Are in the Viewport in Dojo

I would like to fire a function when a user is scrolling and reaches a certain element, so that I can mark that element "read" (think of how posts were marked read after viewing them in the now defunct Google Reader). So, for example, imagine a page like the following:
<div id="1">Node 1</div>
<div id="2">Node 2</div>
<div id="3">Node 3</div>
<div id="4">Node 4</div>
Assuming only the first two <divs> fit within the viewport, I would like to use Dojo's event listener and fire an event when div 3 came into view and again when div 4 came into view. (In addition to my goal of recording when an element has been read, this would also allow me to easily implement infinite scrolling.)
The jQuery Waypoints tool seems to do exactly what I want, but since most of my code uses Dojo, I really don't want to use jQuery just for this one task. I'd like to find a prewritten tool or simple method for doing this that isn't dependent on a library/toolkit other than Dojo (I'm fine with it using Dojo or no library at all).
UPDATE: It appears Skrollr also does what I am looking for, but only for animation -- that is, it can animate an element based on its relationship to the viewport. This doesn't exactly help, though, since my goal isn't animation but to activate a function (that will make an AJAX call via Dojo) when an element comes within the viewpoint.
Thanks to a few pointers from a friend, I was able to put together a functional solution to this question. Assuming all the divs are within another div with the id articles, when the user scrolls the bottom of the element at least 50px into the viewport, I then apply a "read" class to the element.
posts = dojo.query("#articles > div");
dojo.connect(window, 'onscroll', function(){
var vs = win.getBox();
var output;
var readCount;
for (var i = 0; i < posts.length; i++) {
var includeScroll = false;
var locInfo = domGeom.position(posts[i], includeScroll)
var fullyOnScreen = locInfo.y + locInfo.h + 50;
if ((fullyOnScreen > 0) && (fullyOnScreen < vs.h)) {
//Apply "read" class to div if it has been scrolled to.
domClass.add(posts[i], "read");
}
if (locInfo.y > vs.h) {
break;
}
}
});
Remaining question: While this solves my goal, I'm not sure it is the most efficient to poll the location of every div in or above the viewport every time the user scrolls -- even multiple times per scroll event. Are there ways to make this more efficient? It seems to run OK on my Core 2 Duo system, but I don't want to be sloppy just because it doesn't seem laggy.
I thought about calculating the position of all of the divs from the absolute top just once on start up and then doing some comparisons between the viewport and the top each time I scroll. This would probably be more efficient, but I'm not sure if the efficiency gains justify the added complexity of the code.

Resources