As you know, for the sake of good performance, we always try to minimize rendering in single page applications. For instance, in React whenever a state or props change inside a component, that change make that component re execute, re evaluate and finally re render.
So, are there any similar conditions in Angular ? and what are the best practices and patterns for reducing extra rendering ?
This is a huge topic to cover here but I would suggest the following article for starters: https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
TLDR;
What happens is that Angular at startup time will patch several low-level browser APIs, such as for example addEventListener, which is the browser function used to register all browser events, including click handlers. Angular will replace addEventListener with a new version
So by extending base functionality, angular understands changes that trigger re-evaluation of values and rerendering needs.
As an extra, we need to mention that the comparisons are not deep inside reference types, so some handling should happen.
In the article, several methods for performance tweaking are mentioned like
On push change detection method.
Disabling automatic detection for a component and triggering the cycles manually.
Using immutable objects with the help of libraries line immutable.js
As you can understand, these being their own pitfalls and considerations
Related
The most confusing thing in this API is for me the reason why use it. I know ReactJS and RxJS and I'm used to the concept when view reacts to data change. So watching changes to DOM, which happens definitely after some mutations to data, I can't see much sense in it. So my question is when (not) use it?
You're thinking of the problem with a situation where you are already one step ahead. If you are using React/RxJS then the actual value of MutationObserver will most likely be very small.
Even within this, however, there is a clear possibility to leverage this. Suppose you are attempting to use a library within your React application that is not explicitly built for it, and modifies the DOM in some way, but want to extend this further or capture something from it. The best example for this would be augmenting FancyGrid further.
Currently, in a component, you would invoke such a library in componentDidMount, the same way the component above is built. However, this is simply fire-and-forget - you don't know when it is done executing, you don't even know what is happening on the "outside".
Enter MutationObserver. With it, before binding such a library to an element, you can use an observer to be notified of when elements are created, track them, and track property changes. The simplest use case for this would be to make a spinner above a (particularly time-consuming on load) grid.
I would like to know if it's fully consistent with the React principles.I made a React App without state and props.I've put pure javascript only inside componentDidMount e.g.
componentDidMount(){
const first = document.getElementById('first');
const second = document.getElementById('second');
function funk(){
console.log(first.innerHTML);
second.innerHTML = "Arrr";
}
funk();
}
Of course it's just an example, my app is far more complex.
Technically speaking, You can (as you may already know).
Should you do it? A big and glowing NO!.
With this approach of targeting the DOM directly, you are bypassing and missing most of the goodness that react has to offer with the Reconciliation and The Diffing Algorithm.
If you really (really) need to target the DOM, you can use react's ref API.
And you can see in their docs it's should be used sparingly :
Don’t Overuse Refs
Your first inclination may be to use refs to “make
things happen” in your app. If this is the case, take a moment and
think more critically about where state should be owned in the
component hierarchy. Often, it becomes clear that the proper place to
“own” that state is at a higher level in the hierarchy. See the
Lifting State Up guide for examples of this.
Yes and no
Yes, you can use it in some cases for utilizing complex jQuery plugins integrating react as a part of your project and so on...
I know that there are lots of haters of such approach but we should also understand business if it's possible to achieve a goal without spending 40-80hrs for coding it yourself - go for it.
No, you should not do any DOM manipulation in component live cycle methods unless you are very good with react and completely understand how things work internally in this library.
Changing DOM in such way will most likely cause performance issues because your components will not be able to utilize shadow DOM, as a result, your components will perform DOM manipulation after every change and could potentially slow down the application.
For instance React's componentWillMount():
This is the only lifecycle hook called on server rendering. Generally, we recommend using the constructor() instead.
And in React's componentDidMount()
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here.
However I do not see anything in the Angular doc specifying which ones are executed on the server and which ones are executed on the browser (or both). Or should I assume that all of them are executed on both? If so, how do you do things that require the DOM (window, document, etc.)?
No, it doesn't. It runs the same hooks.
There's plenty of devices you can use to avoid contact with plain DOM, like HostBinding and HostListener decorators, Renderer and ElementRef classes. Remember that Angular 2 is a high-abstraction tool. It doesn't promotes access the DOM, although it is possible. Also, for server-side rendering, DI also comes to the rescue when there are different implementations for server and client.
Learn about Angular Universal to know more about server-side rendering at https://github.com/angular/universal.
If that doesn't answer your question, please place a more specific question.
I'm having a huge form built with react and material-ui. The form uses two way binding and update state for input changes. changing any input filed cause all components to update (obvious by react developer tools TraceReactUpdate enabled). When it comes to TextField it makes my page rendering very slow. using this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this) doesn't help.
It can be extremely difficult to find issues like the above, because it totally depends on the actual code you have written. I am sure that the react rendering concept works (as it has for myself and so many others), but without seeing more code it is impossible to pinpoint the actual problem.
Still, I have a feeling that the real cause is "simple", meaning that it is very likely due to a prop being passed that has indeed changed. Maybe not in value, but in instance. IIRC, the PurerenderMixin is not comparing values (unless the data are value types), it is comparing instances. So even if the data is the same, if the instance has changed then it will re-render.
Some key-points to consider:
Are you passing just the props that you need to each component, or are you passing all props to them all?
Are the data-structures immutable?
Are you sure that you are not passing data that changes on the iterations, like passing the javascript [] as a prop will mean that the data has changed (see https://medium.com/#esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f#.hx97qk4tx for sample on how this can screw up your day).
If you explicitly create a shouldComponentUpdate() method for the components then you can control this yourself. The PureRenderMixin does a shallow check to see if the props have changed, but, if you are passing them all then no matter if they have been used or not in the render method then just one of them changing will mean that the component is considered to need to render (as in, not mount, but render in memory and reconcile possible changes with the dom). Using shouldComponentUpdate can help stop rendering based on your own checks.
Using immutable props can also be helpful. The React PureRenderMixin only does a shallow comparison, as mentioned. So, if you are passing data-structures in the props that have depth (like sub-properties), then these are not checked. Meaning that you could end up with the opposite problem you have now, that is components that should have updated but aren't. If you are using i.e. redux and have done "the right thing" and are using i.e. Immutable.js, then using the PureRenderMixin is good enough.
Reading the specific docs for this may or may not help. There's some good description of this in the React manuals: https://facebook.github.io/react/docs/advanced-performance.html#shouldcomponentupdate-in-action
And - I forgot to say, if you are using redux then you could consider these somewhat elegant and simple ways of handling your forms:
http://redux-form.com/
https://davidkpiano.github.io/react-redux-form/
Hope that this helps. Good luck.
I'm new to ReactJS and I'm trying to figure out how to store and manipulate global state. For example, I'm writing an editor app that has some global state: selected color/background, active tool, current selection, etc.
I'm thinking about having a root interface component to store this information, and I'm ok with explicitly passing the state around using properties. I guess the idiomatic way for a children component to change global state is calling a callback received from the parent - personally I find this a bit annoying.
Instead, I'm firing custom events at the children and setting listeners on the parent. So far it is working really well, but I looked at a lot of sample code and never saw people using this pattern.
Is there any practical consequences I should consider?
Flux is great for manipulating global state because the Stores are globally accessible. Globals are known to be bad, but the way you interact with the Stores is through Actions. Actions make the state predictable and localized. So even though the state storage itself is global, Actions make the state interactions very local. At work we tend to do both reading & writing through Actions, so every state change is an "event" that leads to easily programmable behavior.
I really wouldn't compare Flux to Angular as their principles and flows are entirely different. Suggest you try Reflux.