I need to implement infinite scrolling in a react app, while my data is huge and the use might keep on scrolling and scrolling for a long time.
All the infinite scrolling solutions that I've found only handle adding the data to the table whole scrolling. But I need to also remove data from the DOM to prevent the app from slowing due to tens of thousands of rows being potentially loaded after some time on the app (think social media feed).
I also don't want to keep all the data in the memory and I need to clean old data while scrolling (up and down).
So basically what I need to do:
Load the first 100 rows (1 page) to the page
When the user scrolls down and getting near the bottom, load next page and add to the bottom
When the page has a large amount of pages (lets say 5 page, or 500 rows) start to remove old pages from the top when the user keeps scrolling down
If the user start scrolling up, we need to reverse the functionality - Request the pages we removed again and add them to their place in the top
Does anyone know of such a solution?
Any recommendations on how to tackle this if I need to build from scratch?
Thanks!
1. Use react-infinite-scroll-component.
Follow instructions in documentation.
You can see basic example here. Here initially array have 20 elements and fetchMoreData function concatinate 20 more elements to it.
Basically you are concatinating, next elements in in array and adding them over, this is the concept of infinite-scroll.
For furthur references, link1, link2.
Or
2. You can implement you custom scrolling as well, like this
Related
I'm building an hybrid app using ionic and AngularJS (AngularJS-material). This app also has an integrated chat built with Node.js and socket.io.
I have the problem now that with only 200 messages the app gets very slow to load all the messages (200ms in Browser -> 4sec in app, even with CrossWalk, and with track by message.id) and also typing in the the textarea to insert the message is slowed down.
I have two solutions to resolve this:
Virtual Repeat (md-virtual-repeat)
Infinite Scroll (ion-infinite-scroll)
1) I think that virtual repeat would be the best solution (I have already implemented it on another page and it scrolls 1500 items like a charm) but the problem is that the messages can have different heights based on their lenghts and md-virtual-repeat requirements are that all the elements must have the same height to work.
2) So maybe we can pivot to the Infinite Scroll method but the problem now is that doing it with the ion-infinite-scroll directive gets a bit tricky since a chat needs to trigger the loadMore() when reaching the top and not the bottom.
So my question is: Does anybody have a workaround to have a smooth/fast ng-repeat inside a chat using or a virtual-repeat directive that can handle different heights or an infinite scroll that works at the top ?
Efficient scroll lists like md-virtual-repeat or collection-repeat need to know the height of each item in order to work. That’s because they need to know the scroll position, e.g. to show a scrollbar or to be able to skip frames for quick swipe-down motions. The scroll position itself can only be found if you know both how much has been scrolled (we need the height of elements above) and how much there is left to scroll (we need the height of elements below).
What you can do is use a factory to compute the height of each element before injecting them into the loop. This can be done by creating a container with the same properties as the target container (e.g. CSS classes), appending the newly-loaded elements, compute their height (using element.offsetHeight), and removing the container after.
Be aware that this is quite heavy and will likely cause a small lag spike.
Couple of things you could try to speed it up.
One would be to use something like quick-ng-repeat: https://github.com/allaud/quick-ng-repeat instead of built in angular js ng-repeat
Another would be to use one time binding where ever possible to prevent angular from constantly looking for changes during every digest cycle: https://docs.angularjs.org/guide/expression#one-time-binding
And of course, if it's possible, try using chrome's developer tool profile option to find out which of the functions are slowing the application down ; )
PS: Might be worth checking out this thread to see how reverse infinite scrolling could be implemented: Implementing a reverse infinite scroll using ngInfiniteScroll directive in AngularJS
Have you taken a look at React.js as a solution? It uses a virtual DOM which makes updating long lists more efficient.
There is an open-source repo on GitHub that mixes Angular and React, called ngReact.
overview:
http://ngreact.github.io/ngReact/
docs:
http://ngreact.github.io/ngReact/docs/ngReact.html
repo:
https://github.com/ngReact/ngReact
Hope this helps.
Using separate binders like rivets could be a good solution,its easy to integrate and its having rv-each to loop
I think the ionic directive collection-repeat might be what you're looking for.
collection-repeat allows an app to show huge lists of items much more
performantly than ng-repeat. It renders into the DOM only as many
items as are currently visible. This means that on a phone screen that
can fit eight items, only the eight items matching the current scroll
position will be rendered.
Look at angular-vs-repeat angular-vs-repeat
Demo: demo
I use line length for calculation height of items.
It's very approximate method. In our app we know, that one English character with font-size 15px will have width about 6.7px (that's fine, if you use monospace font, but it's not our case). Also we always know width of each segments and height of one text line.
itemHeight = commulativeTextLenght / lineWidth + paddingsOfItem;
Also line break stile can affect your calculation. In general we had a not bad method to calculate heights of about 8000 text paragraphs.
Is there any javascript code or any other way to convert infinite scroll into pagination on facebook or any other website.
Or is there any way to load more results while scrolling using javascript ?
Infinite scroll is easy to develop. But infinite scroll only appends contents. Therefore, if contents are long, scrolling is so slow and the browser is blocked.
If you consider long contents and high performance, I recommended eg.infiniteGrid.
eg.infiniteGrid keeps a number of DOMs when scrolling.
If a user scrolls down, eg.infiniteGrid remove top DOMs. If a user scrolls up, eg.infiniteGrid remove bottom DOMs.
Therefore, eg.infiniteGrid has high performance.
Checks out this video: eg.infiniteGrid benchmark: append item performance
There are a few Javascript/jQuery plugins you can use to implement infinite scrolling on your website. One of them you could check out is jScroll (http://jscroll.com/).
If you're loading paginated content from Facebook or another API, you could use the callback method in jScroll to make a request to fetch each page of data.
I have a basic webpage that polls the backend for new/archived tweets. The returned tweets(JSON) are shown one at a time sliding into view from above the viewport, pausing at the middle and then sliding out below the viewport for the next tweet to display. Animation is via applying a Greensock tween to each tweet item and appending it to an animation timeline for playback.
What are suitable ways to approach this correctly? My main concerns are with how I should insert/update the DOM with the tweet items, and any performance issues I might need to be aware of or cater to(Memory / Layout / Rendering(CSS/Images)).
I am fairly new to web development. My current code uses JQuery to append each tweet into a container div, each tweet is positioned(position:fixed) outside of the viewport and visibility:hidden. I'm presently using embedded tweets with the twttr.js lib which is somewhat problematic due to several issues iframes cause. I plan to transition to my own html snippet + css/js instead.
With plain html or html from template engines like Handlebars or Dust, would it still be a good idea to insert the html for the tweet item like I'm currently doing with the iframe embeds approach? I've yet to use a template engine but understand they have a feature called partials that may be more useful than declaring the html and data logic all in my JS file?
The other concern I have is that as I append tweets currently, due to how the iframe embeds work they're a bit slow to render so need to be preloaded/added ahead of time, and remain in the DOM if manipulating the animation sequence timeline(rewind/fast-forward/scrubbing) due to having to reload again if added/removed. I've seen this cause performance issues with the smoothness of the animation as the amount of tweets in the DOM grows, in addition to memory I guess(not sure by how much).
Switching from using twitters iframe embeds(one per tweet) is probably going to make quite a difference in itself. Is it still a good idea to keep the added html for each tweet piling up? If I have the animation sequence add/remove/recycle(not sure if I'd benefit from an object pool?) the html for each tweet item, am I going to be causing layout/rendering all the time with the CSS as opposed to positioning off the viewport or toggling visibility/display properties? While I don't plan to match the iframe embeds display featureset, I would like to include photo's for the tweets that contain one, thus height would be variable.
I have a menu with custom drop downs that can contain thousands of items. This is the worse case scenario and most of the time it's in the hundreds or less and it's all super fast.
I've delayed the insertion of the elements (li) to when the menu is opened but this causes a perceptible delay for a couple seconds when it's clicked to when it's opened.
I build a string of all the list items in javascript and add it using a single innerHtml assignment. It's the innerHtml assignment that takes all the time. I've also tried using a fragment and appending to that as well as using a fragment and appending each item separately all to no avail. Insertion times are below:
Text Li/InnerHTML Li/Inner/Fragment CreateLI/Fragment
Chrome 13ms 40ms 48ms 138ms
IE9 22ms 2402ms 2364ms 7934ms
IE11 19ms 1952ms 2330ms 4208ms
First column is inserting all the content but just as text and new lines inside pre tags in a single innerHTML call. Unfortunately li's are needed for styling and events ect.
Second column is adding all the content but each wrapped in li tags in a single innerHTML call.
Third column as above but using a fragment and then appending that.
Forth column as above but each li is added as a separate create and append to the fragment.
Unfortunately IE (We are moving to IE11 around xmas) is the target browser - corporate intranet :-(
One thing I've tried to mitigate this is to just insert the first, say 50 items. So opening the menu is fast but on scroll, I have to load subsequent items again in batches of 50 up to the scroll point. IE isn't fast enough so most of the time you are seeing nothing and when dragging the scroll bar it keeps locking, jumping forward, locking ect because the innerHTML calls block the whole browser when you're trying to scroll.
Another technique I've tried is to insert the first 50 items, and then load the remaining in 50 chunks with intervals of say 50ms to not block everything. Unfortunately this leads to an even worse experience because the page responsiveness stutters like it does when scrolling in the previous example, but here you don't even have to be scrolling, it always does it until all the items are added.
I'm out of idea's now. How can I make IE work faster?
Half-assed answer first: The maximum (for you) is 8 seconds long. You could do a modal overlay that shows a loading animated gif that counts from 0% to 100% over an eight second period. I can link you to some code that does that animation in an HTML5 canvas if you want. This is not a great solution, but it would give your users something to look at while the page is taking so long to load.
Arguably better answer: Do what you suggested to yourself - load the first 50 and then load the next X on scroll or every X milliseconds (I like the former better) and just edit your CSS and other code to make sure the page doesn't do weird stuff style wise like you seem to be experiencing in your tests.
Best answer: You say that it's a custom menu, but it is a menu. As such, you should cache it instead of loading it fresh every time. You create the cache text file every time the menu is changed in the database. Loading a text file into the page will take almost no time and every programming language you work with can do it. The way this works is you make a function that builds a .txt file containing the pure HTML of the menu and then call that function every time the menu update function is run (after the database is updated, naturally).
I am making a portfolio website and have a horizontal slider which will slide between each piece of work. Let's assume that there are 100 works and they are all graphically intensive and/or flash objects.
Let's also assume that there will be a maximum of 4 works on screen at any one time.
They are all in one large div which I manipulate with jQuery to modify the left property to move the div.
On a high end machine it works nice and smooth but on for example a netbook, it's really choppy... or even on a slower browser.
What I plan on doing is working out which works will be visible as they transition and show only them. I hope this will give a performance increase. However, I plan on setting the visibility property to hidden so the elements dimensions are still there. But, I am wondering would it be better performance wise to set the display to none and create a placeholder element instead of just hiding the work?
What other ways could I increase performance on slower machines/browsers?
You will not gain any feelable performance increase from just making display:none;. The content will still be loaded.
Instead you could try to look at some ajax. An idea would be to preload 8 items even though you only show 4. Then at the users click on the "next"-button, the screen slides to the next 4 already loaded items and at the same time the next 4 items in the row will begin to load.
http://yensdesign.com/2008/12/how-to-load-content-via-ajax-in-jquery/