vdom is finally updating the dom (after diffing) any dom change should actually trigger repaint & reflow of entire tree, then what is the use of vdom? - reactjs

This question was asked manier times whenever we change a dom , like
Method 1 :
document.getElementByID('root')="hello"; even for changing one dom element , the browser rerenders the whole dom and state of the other elements like input text boxes will be lost, and recomputes styling and layouts (.ie reflows and repaints )
It is fine till now.
Method 2:
What react does is it keeps a virtual dom which is a copy of real dom, whenever a state changes, it rerenders entire new vdom in memory and does diffing and identifies which nodes to be updated in real-dom and react updates only that part in real-dom ,thus saving time not re-rendering entire dom.
My Question is at the end of the day either we update the realdom using method 1 or by using a vdom , finally dom is getting updated which in turn should make the browser compute the whole layout and styles again, why people say it helps to update only some part of the UI?
** Please kindly refrain from answering the same diffing concept, vdom concept, updating the required parts concept,or repaint and reflow process i.e dom tree css tree and rendering engine etc...**
# My question is how vdom can stop browser repainting and reflowing when ultimately dom is getting updated which in turn makes reflow and repaint whole tree?
picture about what I am trying to ask:
Ignore my grammar, and correct me where ever I am wrong at concepts of dom, vdom, repaint and reflow.

VDom will generally not save you any repaints/reflows compared to well-written DOM manipulation.
The main benefit of it is that it that it allows for a declarative component API. You describe what the component is, and React figures out how to render it efficiently without re-generating extraneous DOM elements. The html changes will generally be smaller using this approach.
Performance benefits here are somewhat of a red-herring. Yes, Reacts vdom has optimizations such as batching renders, but these are optimizations for the vdom, not for the browser. Browser DOM operations are already very fast.

Related

React - to manipulate DOM or use state?

This Is more of a "theoretical" question that often buffles me in different situations and use cases, I will give a simple example to demonstrate it.
Let's say I have a list of 10 buttons.
Everrytime I click a button, a floating menu appears on top of the clicked button - there is only one menu visible for any given time.
Let's assume that I can't render this floating menu within the button component and I can only render it in the buttons parent level (meaning that this menu is sibling to those buttons).
I have 2 possible options to do that:
Keep the x,y position of the last clicked button and render the menu in this given position
Render the menu once and using "ref" to directly relocate the menu
On the one hand, the first approach seems more "Reactish". On the other hand, the possible implemention I can think of is pretty ugly (capturing the clicked item position and saving it to state which triggers defender), and further more, I am not so sure about re re rendering the whole container just because I need to move a small piece of it.
The second approach touches the DOM directly using refs. Although possible , doing DOM manipulations sometimes feel bad to me.
Is there a better approach? Which of the 2 makes more sense?
Any suggestion or thoughts will be appreciated!
Thanks
React uses whats called a virtual DOM, which is a representation of the DOM, that sits on top of the real browser DOM. Whenever you update state or a user performs an action the virtual DOM compares and checks the changes with the real DOM and then updates the UI accordingly.
So if certain DOM elements like a are not different between changes it does not get re rendered, only the DOM elements that have changed are re rendered. And if a property on a DOM element is changed, only the property is updated and the DOM element is not re rendered.
<div color="blue" />
to
<div color="red" />
The whole element is not destroyed and re created, only the property is changed.
However if the element in the host tree is different than the entire host tree is destroyed and recreated.
<div />
to
<p>
This is refereed to as reconciliation
https://reactjs.org/docs/reconciliation.html
So using refs is definitely more of a hacky solution since its more of an escape hatch and directly manipulates the DOM.
I would definitely stick with option 1, I think there is an elegant solution to the use case you described, it would involve just adding a click event listener in the componentDidMount and keeping track of the click position that way.
And also its hard to say without code but since your buttons will be the same, they will not be re rendered only the menu will.
Would recommend for further reading
https://overreacted.io/react-as-a-ui-runtime/

Can I see specifically what React's diffing algorithm is detecting has changed?

I'd like to gain visibility on the React shadow DOM diffing algorithm to debug a problem I'm having. Specifically, I'd like to see exactly what React will be changing on the next render. Only the className? The entire element?
tl;dr if you're curious, I have a css transition triggered by a class change which doesn't work, so I'm trying to figure out whether it's because React is seeing more changes than just the class and replacing the entire element (which I believe would prevent any style transitions from working).

Dealing with frequent updates to a large React component

I have a large React component with scrollbars. I'd like to make some small changes to a few components when it scrolls (basically to keep the left-most column of a table stuck to the left side of the screen).
Normally I'd pass props indicating the component's scroll position down to the components that need to update when it scrolls, but re-rendering the whole component when it scrolls makes the whole thing massively laggy. But the whole thing doesn't really need to be re-rendered -- only a few small parts of it to make sure they stay in the right part of the screen
Is there a good way to re-render only a small part of a component, or is there another way of dealing with frequent updates to large components like this?
Implementation might get a bit hairy but have you had a look into shouldComponentUpdate? (docs)
You could probably track the scrolling and use it to skip updating on the pieces you don't want to update - eg. pass an isScrolling prop to some children and skip update if it's true, or only update if the scoll distance has changed by a certain amount or a certain amount of time has passed.
Depending on the visual effect you want another option is to replace the content of the slow part with a placeholder which is more easily rendered when the isScrolling prop is set - we do something similar with an isLoading prop and loading GIFs, which works well.

Is React's data-binding really one way? It seems like it is two way

This is from a couple React tutorials that I'm currently reading:
the State drives what the guys at Facebook call one-way reactive data
flow, meaning that our UI will react to every change of state.
and
Typically UI’s have lots of state which makes managing state
difficult. By re-rendering the virtual DOM every time any state change
occurs, React makes it easier to think about what state your
application is in. The process looks something like this, Signal
to notify our app some data has changed→ Re-render virtual DOM ->
Diff previous virtual DOM with new virtual DOM -> Only update real DOM
with necessary changes.
The first quote seems to suggest that the data flow goes from React to the UI. But the second quote seems to suggest that it goes from the DOM to React which then re-renders the virtual DOM and the diff process than repaints the real DOM. This sounds a lot like Angular's two-way data binding.
Is this true? What am I missing? Is one-way reactive data flow just another name for Angular's two-way data binding?
I think it's necessary to make a distinction between React and Flux, both of which implement a uni-directional data flow. I'll only touch on React here.
In Angular a change to the DOM will directly mutate the value of bound scope variables in your controller thanks to angular's two-way data binding and the digest loop. It is two way because, of course, any change in your controller is also directly reflected in the view attached to it.
Think of Angular as Controller <--> View
In React a component always renders its DOM based on its props and internal state. A React component can listen to event being fired in the DOM it rendered, which might sound a bit like two-way data flow on the face of it but there is an important difference: An event fired on the DOM does not directly update the internal state of the component. The component must listen to the event and then explicitly update the component with the new state. This change of state then triggers the DOM to be re-rendered (if it needs to). In this way the components props and state are the single source of truth and always drive the DOM output. Of course changes in the DOM can affect the component but it is done in an indirect manner.
Think of React as Component State --> DOM --> New Component State --> New DOM
Angular's two way of binding's essence is that the view is bound both to the model and the user's input.
With React, the view is bound only to the state and a user's input cannot directly change the view, but triggers the component's own methods to update its state and Reacts job is to rerender the view so it reflects the state.
The flow here is:
Component
state-> virtual DOM -> DOM
This is always the flow, whether its initial render or second render.
The quoted bit is:state->virtual DOM -> DOM
newStateDifferentFromOldState -> virtual DOM
diff virtual DOM from 1 with virtual DOM from 2
Only update the elements of the DOM that are the net difference of performing 3.
e.g. 1->2->3->4, repeat in this order from 2 (2->3->4->2->3->4...so on)
This is in no way related to the concept of two way data binding.

Is it possible to have a component update right after shouldComponentUpdate, but before the next component's ShouldComponentUpdate is called?

So far I am loving React, but there is one part of my application (and unfortunately a crucial part) that I have hit a bit of a hiccup with.
When an item mounts or flushes updates to the dom, I need to do specific checks around the finalized HTML before I continue (for example, if the component's dom nodes are overflowing the container I need to move it to the next container).
The problem with this is shouldComponentUpdate is called for all of them before any of them have componentDidUpdate. This means I have to wait until all components flush to the dom, before I iterate through them in order to calculate from top to bottom if they overflow their outer container, and if so I need to change some things up causing all components after that one to be forced to update.
For example if my parent has 20 components and the 3rd component overflows, I have to wait until all 20 components are flushed to the dom before I move the latter 17 components to the next container, just to repeat until all components fit inside their containers.
What I would love to happen is that the first component flushes, I check if it overflows, then the 2nd component flushes, then I check if it overflows, etc... That will drastically decrease how much is flushing to the dom.
Is this at all possible with Reaact?
If you are curious on the why behind this question, you can see this question
No, it's not possible to directly cause React to sequentially call shouldComponentUpdate between component DOM flushes. In fact, that could dramatically and negatively affect the performance gains often realized by new React code by flushing all DOM changes between each call.
Instead, I believe you'll need to move to a model where a container component iteratively renders the children components either on- or off-screen and then lays out the children appropriately. The parent component would need to use the callback componentDidUpdate to measure children after they have rendered. Then, using setState for example, trigger the addition of a new child until the loop was complete. Eventually, all children will be rendered. This technique should operate relatively quickly and isolates the DOM and measuring of components as much as possible (rather than impacting the entire page for example). If you could render the children to an off-screen component/DOM element for measurements, it may be slightly faster. In fact, if you could render all the children off-screen in a single pass for measurements, that might be ideal.

Resources