What actually makes update using React faster that regular UI update? - javascript

I have already read 10 articles about React and Virtual DOM.
I understand that virtual DOM uses the diffing algorithm and only update the UI that was changed. But I still don't understand why that is faster than updating the actual DOM.
Following is an example:
<div id="test">
Hello React!
</div>
Let's say we created a component and changed it using React. Let's say we changed the text to Hello World!
I can do the same thing using plain JS right ? document.getElementById('test').innerHTML = Hello World!
My question:
Why is React faster ? I feel like React is doing exactly same thing under the hood right ?
I feel like I am missing something fundamental here.

In your case the plain js function will be definetly faster. React is just very good for really complicated UIs. The more complicated your UI gets, you either need to write a lot code to update it or you just rebuild the whole UI on every rerender. However those DOM updates are quite slow. React allows you to completely rerender your data but actually not rerender the whole DOM but just update some parts of it.

Actually the Virtual Dom is not faster than the actual Dom , The real DOM itself is fast, it can search, remove and modify elements from the DOM tree quickly. However the layout and painting elements in html tree is slow. But React virtual DOM is not faster. The real benefit from Virtual DOM is it allows calculation the different between each changes and make make minimal changes into the HTML document.
Now why react is better when it come to manipulating the DOM?,your browser does a lot of work to update the DOM. Changing the DOM can trigger reflows and repaints; when one thing changes, the browser has to re-calculate the position of other elements in the flow of the page, and also has to do work re-drawing.
The browser has its own internal optimization to reduce the impact of DOM changes (e.g. doing repaints on the GPU, isolating some repaints on their own layers, etc), but broadly speaking, changing a few things can trigger expensive reflows and repaints.
It's common even when writing everything from scratch to build UI off the DOM, then insert it all at once (e.g. document.createElement a div and insert a whole tree under it for attaching to the main DOM), but React is engineered to watch changes and intelligently update small parts of the DOM to minimize the impact of reflows and repaints

A few reasons off the top of my head:
React uses a virtual DOM, which are just JS objects, to represent the DOM. The "current" version of the virtual DOM are objects with references to the actual DOM elements while the "next" vDOM are just objects. Objects are incredibly fast to manipulate because they are just memory changes whereas real DOM changes require expensive style layout, paint and rasterization steps.
React diffs the current vDOM against the next vDOM to produce the smallest number of changes required to make the real DOM reflect the next vDOM. This is called reconciliation. The fewer changes you make to the DOM, the faster layout calculations will be.
React batches DOM changes together so that it touches the real DOM as few times as possible. It also uses requestAnimationFrame everywhere to ensure that real DOM changes play "nicely" with the browser's layout calculation cycles.
Finally (probably React's least appreciated feature), React has increasingly sophisticated scheduling step to distinguish between low- and high-priority updates. Low priority updates are UI updates that can afford to take longer e.g. data fetched from servers whereas high-priority updates are things that the user will notice right away e.g. user input fields. Low priority updates use the very new requestIdleCalback API to ensure that they run when the browser's main thread is actually idle and that they frequently yield back to the main thread to avoid locking up the UI.

why that is faster than updating the actual DOM.
It is not faster. Explicit and controllable DOM updates are faster than anything else.
React may schedule better update graphs on sites similar to facebook but with the cost of diff processing O(D*N). On other sites React could be just a waste of CPU power.
No silver bullet here - each framework is optimal for the site it was created for initially. For others you will be lucky if particular framework is at least sub-optimal.
Real and complex Web App UIs are not using any "framework" but their own primitives: GMail, Google Docs, etc.

You might just use vanilla-js as you described:
document.getElementById('test').innerHTML = Hello World!
that's great, but super hard for medium \ big projects.
why? because react handle all your dom interaction and minmize it (as much as it could), when you would use vanilla-js most of your code would be just manipulation on the dom, extract data and insert data, with react you can put those worries aside and put all your afforts to create the best site\project.
more over, the virtual dom makes all the calculation behinde the sense, when you would try to do it manulay you have to deal with all the calculation every time (when you update an list and when you update another one), most probably from some point most of your code would be calculation about the dom updates
sound familiar? well, just for that you already got react.
Don't Repeat Yourself
if someone already done it, reuse it.
Separation Of Concerns
one part of your project should manipulate the ui, another should manipulate the logic
and the list can go on and on, but in conclusion the most important thing, vanilla-js is faster, in the end with the virtual dom and without it, you would have to use vanilla-js in the end. make your life simpler, make your code readable.

React is NOT faster then PURE Javascript.
The big difference between them is :
Pure Javascript: if you can master the Javascript language and have time to spend to find the best solution (with the lowest impact in browser performance) you definitively got an UI render system more powerful then React (because you have created a specific engine oriented to your necessity)
React: if you want to spend more time in data structure with no worries on UI update performance React (or Vue.js the future candidate for UI developing) is the best choice

Related

Creating a React component and states from regex string matches

I'm moving the frontend of a project I'd written primarily with php and jquery over to react as a learning exercise. So far it just seems to be making everything a bit more convoluted but I'm hoping I'll see the benefits soon. Right now it's just good to be familiarising myself with something far more current than what I was using. But I digress...
There's one particular situation I'm translating at the moment that feels simple to do in jquery but feels like I'm having to choose between a bunch of cumbersome or not-recommended solutions with react, such as dangerouslysetinnerhtml
A user can input their own list, as raw text, which the app parses using regex to highlight quantities and items, illustrated above as highlighted by rose and green. New lines are parsed as list elements, highlighted in peach. The parsed quantities can be scaled using a range input, shown above the list. The example UI shows an example after parsing a raw string of text.
Previously - jquery
When I was using jquery I replaced regex matches with <span> elements containing data attributes to create new elements I could target. The quantity scaling function in the app could now reference the original quantity of a list item at any time using a data attribute.
e.g. I need 10 cars is parsed to become <li>I need <span class='highlight quantity' data-count='10'>10</span> <span class='highlight item' data-item='cars'>cars</span></li>
With jquery, whenever the input range is dragged, I just target all elements on the page that have the quantity class, reference their data-count and replace the span value with the current range value multiplied by that data-count. This worked well.
Now - React
I'm getting my head around react components. Referencing the illustration, above, I have a component for dialogs (as there will be other dialogs too), a component for the range input of dialogs, a component for the list, and a component for list items.
As before, when I drag the input range, I want the quantities on the page to change to reflect the new scale set by a user. When picking up react I became familiar with component states and props and thought these would solve my problem beautifully. If I had a scale state I could pass it through the components and anything in the hierarchy could reference it. As I understood it, the hierarchy was important and it was important to hold the state at the top so that lower-level components could be 'fed' it, if that's a good way of putting it. This appeared to be best practice.
But I'm having a tough time getting it to jump through hoops. Maybe I've misunderstood?
Two uncertainties
1
If I've understood the hierarchy of states correctly, I'm setting the state initially inside the App() function, like so:
function App() {
const [scaleValue, setScaleValue] = useState();
const handleScaleChange = (childData) => {
setScaleValue(childData);
}
return (
<React.Fragment>
/~~~/
<UserList rawstring={userText} scale={scaleValue} />
/~~~/
<Dialogs scale={scaleValue} setscale={setScaleValue} parentCallback={handleScaleChange}/>
</React.Fragment>
);
}
But I must use a callback function to change the state as the dialog range I'm using is nested a few levels down in components - passing it back to the state in the parent App() function and then back down to all the nested components using props. It felt much easier to just target elements with a matching class name in jquery and I'm not yet seeing the advantage of having components using states. I thought being able to target list item components with quantity states would have advantages in React that were more apparent.
2
Perhaps the main thing that has me stumped on how to proceed. In jquery, when I was parsing a raw string provided by the user, into html that I could target with specific classes, I just used some regex functions to return html that could be inserted into the dom. Example of the html is per the earlier example:
I need 10 cars is parsed to become <li>I need <span class='highlight quantity' data-count='10'>10</span> <span class='highlight item' data-item='cars'>cars</span></li>
With react, I parse the same string to the same html fine, but I've no idea how to handle it from there, logically? If I return it and insert it, it is treated as raw text and renders the html tags on page. I can use dangerouslysetinnerhtml and it shows fine, but I've loud and clear got the message that this is heavily discouraged. I want to use best practices.
In fact, I likely don't want to be returning quantities wrapped in targetable classes. I gather that I want to be able to assign states to a list item component. I have absolutely no idea what's the best approach (logically) to do this with react. I could return an array from the regex parsing but this feels needlessly complex compared to replacing a matched sub string with a wrapped version of itself.
I feel at this point I may be approaching the translation wrong (or my understanding of using the component system and states) as this feels so much more convoluted than the jquery approach I was using.
not-recommended solutions with react, such as dangerouslysetinnerhtml
That's not what dangerouslySetInnerHTML is about. It's about the fact that an unsanitized string containing HTML/JS could pose a security threat (XSS mostly). In other words, in React you have to explicitly use dangerouslySetInnerHTML if you need to be unsafe, but it's your responsibility to protect yourself, hence the name. Doesn't mean it's not recommended, just tells you to be extra careful.
the hierarchy was important and it was important to hold the state at
the top so that lower-level components could be 'fed' it, if that's a
good way of putting it.
Indeed, at first it might look overly complicated for no good reason. Today.
A few months from now if you'll have to go through that code again, or worse, if someone else will have to, this structure enforcing rules and structure makes it far more easier to make changes. You can simply right click on the "callback" function and "go to definition" in your IDE of choice and see where it's defined, instead of hoping it's not hidden in some JS file or relying on search when the function is named "handleClick" in a project with one thousand click handlers.
It felt much easier to just target elements with a matching class name in jquery
Of course it was, anyone with minimal experience in a large scale project knows this. There always are trade-offs. You need to judge if it makes sense to loose simplicity for the sake of maintainability based on the scale of the project.
With react, I parse the same string to the same html fine, but I've no idea how to handle it from there, logically?
You are mixing parsing with generating HTML. You were parsing the string and generating HTML. With React you have to parse the string and generate JSX. If your code was separating these two concerns then it would have been a lot clearer what the difference is.
Again, if you are the only one working on this and know you'll never touch it again, why bother separating these two parts? On the other hand if you do expect to touch that piece of code later or know there will be other people working on it then the smart option would be to split it so that you can properly unit test it.
I can use dangerouslysetinnerhtml and it shows fine, but I've loud and clear got the message that this is heavily discouraged. I want to use best practices.
No, that's not the point. If you use dangerouslySetInnerHTML then how are you going to interact with those highlighted numbers? document.querySelectorAll? That is indeed against the purpose of React. I think my answers above make it clear what a more suitable approach would be.
feels needlessly complex compared to replacing a matched sub string with a wrapped version of itself.
And it is because you don't understand why someone would use React. You think React is a replacement for jQuery and it is not. It is a way of writing JavaScript applications so that you don't end up with a pile of code no one can follow. Which is a problem that only exists if you eventually end up with a lot of code. Your application has what, 100 lines of JavaScript? Why are you even using jQuery?
My advice is:
Understand that people that make deliberate choices don't choose React because it's fashionable but because it solves some problems.
Figure out what those problems are. I've listed a big one, which is maintainability and that structure and separation of concerns are part of the solution.
Decide if you care about any of the problems React helps solve in any of the projects you work (or will work) on.
If you do care about these problems then put yourself in the appropriate state of mind. React is not meant to replace jQuery, find a project that would benefit from using React.
Understand that React is not the one and only tool you'll ever need.
Some more advice:
definitely have a look at useReducer and then (if you need the extra juicy bits) Redux for state management. All beginner tutorials try to stay away from them but IMO React is an empty shell without proper state management.
React is a clean way of turning state into HTML/CSS. The philosophy is that any action (e.g. a click on a "add a new row" button) should produce a state mutation that translates into manipulating some data, NOT the DOM. Your JSX is one representation of that data! And React does a great (fast) job at manipulating the DOM to reflect the new JSX representation. So start thinking your application in terms of input-output, data structures and actions/reducers that manipulate these data structures.
force yourself to unit test (or, better, TDD) your actions and reducers. Completely decoupled from JSX and DOM! Your entire application logic should be testable in Node CLI. This to me (that you can completely separate logic from presentation) is a major win (and is the base of React Native too).
have a look at https://storybook.js.org/ - this one is another one of those fantastic tools (not only for React) that will completely change your development experience.
be wary of using "component libraries". Most "complicated" things turn into child's play when you really understand how to design them correctly.
be prepared to spend 3x the time you spent before on implementing really simple stuff for a while, until you familiarize yourself with the core concepts and philosophy.

Limitation of Angular and browsers with regards to data loaded

I would like to know what is the maximum data that angular framework can handle. Say, I am displaying a chart using angular and some charting framework like chartjs. I'd like to know up to how many data can the browser display properly, with slowness, or up to when it crashes.
Your question has no simple answer, but I will try to flatten it and give a simple answer, or at least simple things to consider...
Angular (at runtime), like many other frameworks is simply JavaScript,
So let us reduce the question to "Limitation of JavaScript and browsers with regards to data loaded",
JavaScript has no upper limit of memory or storage it can handle,
I've seen JavaScript applications that require more than 15GB of RAM,
and they performed well too.
So assume data size itself is not an issue (unless your application is poorly implemented, leaking memory or just not very efficient, of course).
The main challenge as I see it, is displaying and manipulating the information
without causing unnecessary delay or unresponsiveness.
Displaying the information - let's say you have a list (or a table) containing 1,000,000 possible gifts which you then want to display for the user to select.
Adding the list items to the document one by one is tempting, but will require the browser to repaint after each addition (causing a delay or full unresponsiveness until finished), another way is adding the elements to some DOM element (denoted by N) still being kept in memory, then adding all elements corresponding the list items to the element N (still, just an in memory operation), finally adding N to the document containing the entire list - the will be a much better solution for displaying the large amount of data.
Manipulating the information - displaying is indeed not enough. you would like to move, drag, sort and filter the data being displayed. And as mentioned before, it is a bad idea removing many elements directly from DOM. You should instead remove container from the document's DOM to memory, manipulate the data in it, and then add the container right back to the document. Angular does this kind of magic for you.
(Toggling the 'display:none\block' css attribute of many elements has a similar blocking effect as I recall).
A good practice is implementing an application/page showing only the amount of data that can be processed by a human at a single glance. The rest of it should be considered in the application data-layer, in memory, and should be loaded to display given the appropriate need or request.
To conclude, you can deal with huge amounts of data as long as you provide a mechanism that efficiently filter the displayed information.
I hope it helps...
for further reading:
Slow and fast ways of adding elements to DOM
A question emphasizes the lack of memory limit used by JS
CSS display attribute performance
A good discussion about the reasons for slow DOM
About using HTML5 correctly - old but still true
Once the DOM creation procedure is understood - it much easier to display data without affecting performance / user experience

do I understand react virtual DOM sense correctly?

My way of thinking:
If we want to perform something on dom element we can do it by:
document.getElementById("#someId").DoSomething();
document.getElementById("#someId").DoSomethingElse();
In that situation browser needs to search entire DOM for #someId object. Then it forgets element and searches again to perform DoSomethingElse().
To solve "forgetting and searching again" problem we can save our element as JavaScript object.
var someElement = document.getElementById("#someId");
someElement .DoSomething();
someElement .DoSomethingElse();
Going further we can save entire group of elements or entire nodes to achieve better performance. One more step and we have whole DOM saved as an JavaScript object named virtual dom.
Is that correct way to understand purpose of virtual DOM?
Sorry for noob questions, I'm not front end developer, I'm just curious :)
The main point of the VirtualDOM is that, effectively, you're working on a copy of the real DOM. But the working with that copy is ways faster that working with the actual DOM, because it only has the thing that React actually needs, leaving specific browser issues aside.
The main problem with working with the actual DOM is that it's slow. At least, it's faster to work with that kind of copy, make your work there, and the changes have been done, then you update the actual DOM.
Yes, it sounds a bit crazy, but is faster to compute the differences between state changes and the change everything in "just one step", than making that changes with the actual DOM.
Additionally, you've used for your example just a single DOM node, but you're working on changes on DOM subtrees the thing is not that easy.
For an explanation with more detail you can take a look to this article: http://reactkungfu.com/2015/10/the-difference-between-virtual-dom-and-dom/

React-like programming without React

I grew up using JQuery and have been following a programming pattern which one could say is "React-like", but not using React. I would like to know how my graphics performance is doing so well, nonetheless.
As an example, in my front-end, I have a table that displays some "state" (in React terms). However, this "state" for me is just kept in global variables. I have an update_table() function which is the central place where updates to the table happen. It takes the "state" and renders the table with it. The first thing it does is call $("#table").empty() to get a clean start and then fills in the rows with the "state" information.
I have some dynamically changing data (the "state") every 2-3 seconds on the server side which I poll using Ajax and once I get the data/"state", I just call update_table().
This is the perfect problem for solving with React, I know. However, after implementing this simple solution with JQuery, I see that it works just fine (I'm not populating a huge table here; I have a max of 20 rows and 5 columns).
I expected to see flickering because of the $("#table").empty() call followed by adding rows one-by-one inside the update_table() function. However, the browser (chrome/safari) somehow seems to be doing a very good job of updating only that elements that have actually changed (Almost as if the browser has an implementation of Virtual DOM/diffing, like React!)
I guess your question is why you can have such a good graphics performance without React.
What you see as a "good graphics performance" really is a matter of definition or, worse, opinion.
The classic Netscape processing cycle (which all modern browsers inherit) has basically four main stages. Here is the full-blown Gecko engine description.
As long as you manipulate the DOM, you're in the "DOM update" stage and no rendering is performed AT ALL. Only when your code yields, the next stage starts. Because of the DOM changes the sizes or positions of some elements may have changed, too. So this stage recomputes the layout. After this stage, the next is rendering, where the pixels are redrawn.
This means that if your code changes a very large number elements in the DOM, they are all still rendered together, and not in an incremental fashion. So, the empty() call does not render if you repopulate the table immediately after.
Now, when you see the pixels of an element like "13872", the rendering stage may render those at the exact same position with the exact same colors. You don't have any change in pixel color, and thus there is no flickering you could see.
That said, your graphics performance is excellent -- yes. But how did you measure it? You just looked at it and decided that it's perfect. Now, visually it really may be very very good. Because all you need is avoid the layout stage from sizing/positioning something differently.
But actual performance is not measured with the lazy eyes of us humans (there are many usability studies in that field, let's say that one frame at 60 Hz takes 16.6 ms, so it is enough to render in less than that). It is measured with an actual metric (updates per second or whatever). Consider that on older machines with older browsers and slower graphics cards your "excellent" performance may look shameful. How do you know it is still good on an old Toshiba tablet with 64 MB graphics memory?
And what about scaling? If you have 100x the elements you have now, are you sure it will scale well? What if some data takes more (or less) space and changes the whole layout? All of these edge conditions may not be covered by your simple approach.
A library like React takes into account those cases you may not have encountered yet, and offers a uniform pattern to approach them.
So if you are happy with your solution you don't need React. I often avoid jQuery because ES5/ES6 is already pretty good these days and I can just jot down 3-4 lines of code using document.getElementById() and such. But I realize that on larger projects or complex cases jQuery is the perfect tool.
Look at React like that: a tool that is useful when you realize you need it, and cumbersome when you think you can do without. It's all up to you :)
When you have something like this:
$("#table").empty()
.html("... new content of the table ... ");
then the following happens:
.empty() removes content and marks rendering tree / layout as invalid.
.html() adds new content and marks rendering tree / layout as invalid.
mark as invalid among other things calls InvalidateRect() (on Windows) that causes the window to receive WM_PAINT event at some point in future.
By handling WM_PAINT the browser will calculate layout and render all the result.
Therefore multiple change requests will be collapsed into single window painting operation.

Executing JavaScript "in the background"

do you have any experiences with the following problem: JavaScript has to run hundreds of performance intensive function calls which cannot be skipped and causing the browser to feel crashed for a few seconds (e.g. no scrolling and clicking)? Example: Imagine 500 calls for getting an elements height and then doing hundreds of DOM modifications, e.g. setting classes etc.
Unfortunately there is no way to avoid the performance intensive tasks. Web workers might be an approach, but they are not very well supported (IE...). I'm thinking of a timeout or callback based step by step rendering giving the browser time to do something in between. Do you have any experiences you can share on this?
Best regards
Take a look at this topic this is some thing related to your question.
How to improve the performance of your java script in your page?
If your doing that much DOM manipulation, you should probably clone the elements in question or the DOM itself, and do the changes on a cached version, and then replace the whole ting in one go or in larger sections, and not one element at the time.
What takes time is'nt so much the calculations and functions etc. but the DOM manipulation itself, and doing that only once, or a couple of times in sections, will greatly improve the speed of what you're doing.
As far as I know web workers aren't really for DOM manipulation, and I don't think there will be much of an advantage in using them, as the problem probably is the fact that you are changing a shitload of elements one by one instead of replacing them all in the DOM in one batch instead.
Here is what I can recommend in this case:
Checking the code again. Try to apply some standard optimisations as suggested, e.g. reducing lookups, making DOM modifications offline (e.g. with document.createDocumentFragment()...). Working with DOM fragments only works in a limited way. Retrieving element height and doing complex formating won't work sufficient.
If 1. does not solve the problem create a rendering solution running on demand, e.g. triggered by a scroll event. Or: Render step by step with timeouts to give the browser time to do something in between, e.g. clicking a button or scrolling.
Short example for step by step rendering in 2.:
var elt = $(...);
function timeConsumingRendering() {
// some rendering here related to the element "elt"
elt = elt.next();
window.setTimeout((function(elt){
return timeConsumingRendering;
})(elt));
}
// start
timeConsumingRendering();

Categories

Resources