Reconciliation in React detailed explanation - reactjs

I am new to react JS. Can anyone explain reconciliation exactly how it works. I have tried understanding it from react official site but didn't got it.

This is how I understand :
You would agree that react makes thing simple and faster using components .
With JSX we can make things easier for user-defined components .
End of the day all of it gets translated to pure JavaScript (I assume you understand how React.createElement works)with function calls holding other function calls as its arguments/properties holding yet other function calls and so on ..
Anyway nothing for us to worry about as react does this on its own internally .
But how does this gives us an UI ?
Why it is faster from other UI libraries ?
<-- ALL HAIL ReactDOM library and the render method -->
An ordinary ReactDOM call looks like this :
// I have avoided the usage of JSX as its get transpiled anyway
ReactDOM.render(
React.createElement(App, { //if any props to pass or child }), // "creating" a component
document.getElementById('#root') // inserting it on a page
);
Heard about VirtualDOM ? { yes : 'Good'} : { no : 'still Good'} ;
The React.createElement construct element object with type and props based on the components we have written and place the child elements under a children key inside props.
It recursively does this and populates a final object which is ready to be converted to HTML equivalent and painted to the Browser.
This is what VirtualDOM is, which resides in reacts memory and react performs all its operation on this rather on actual Browser DOM .
It looks something like this:
{
type: 'div',// could be other html'span' or user-diff 'MyComponent'
props: {
className: 'cn',
//other props ...
children: [
'Content 1!', // could be a component itself
'Content 2!', // could be a component itself
'Content n!', // could be a component itself
]
}
}
After a Virtual DOM object is built, ReactDOM.render will transform it into a DOM node our browser can paint the UI according to those rules:
If a type attribute holds a string with a tag name—create a tag with all attributes listed under props.
If we have a function or a class under type—call it and repeat the process recursively on a result.
If there are any children under props—repeat the process for each child one by one and place results inside the parent’s DOM node.
The Browser paints it to the UI , this is an expensive task .
React is very smart to understand this.
Updating the component means creation of a new object and paint to UI. Even if a small change is involved it will make the whole DOM tree recreated .
So how do we make the Browser never have to create DOM each time rather paint only the necessary things.
This is where we need Reconciliation and the diffing algorithm of React ..
Thanks to react we don't have to do it our self manually , its taken care of internally here is a nice article to understand deeper
Now you can even refer the official React docs for Reconsiliation
Few points worth noting :
React implements a heuristic O(n) algorithm based on two assumptions:
1) Two elements of different types will produce different trees.
2) The developer can hint at which child elements may be stable across different renders with a key prop.
In practice, these assumptions are valid for almost all practical use cases.
If these are not met it will cause performance issues.
I am just copy Pasting few other points just to give a idea how its done :
Diffing :
When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements.
Scenario 1: type is a string, type stayed the same across calls, props did not change either.
// before update
{ type: 'div', props: { className: 'cn' , title : 'stuff'} }
// after update
{ type: 'div', props: { className: 'cn' , title : 'stuff'} }
That is the simplest case: DOM stays the same.
Scenario 2: type is still the same string, props are different.
// before update:
{ type: 'div', props: { className: 'cn' } }
// after update:
{ type: 'div', props: { className: 'cnn' } }
As type still represents an HTML element,React looks at the attributes of both, React knows how to change its properties through standard DOM API calls, without removing the underlying DOM node from a DOM tree.
React also knows to update only the properties that changed. For example:
<div style={{color: 'red', fontWeight: 'bold'}} />
<div style={{color: 'green', fontWeight: 'bold'}} />
When converting between these two elements, React knows to only modify the color style, not the fontWeight.
///////When a component updates, the instance stays the same, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, and calls componentWillReceiveProps() and componentWillUpdate() on the underlying instance.
Next, the render() method is called and the diff algorithm recurses on the previous result and the new result.
After handling the DOM node, React then recurses on the children.
Scenario 3: type has changed to a different String, or from String to a component.
// before update:
{ type: 'div', props: { className: 'cn' } }
// after update:
{ type: 'span', props: { className: 'cn' } }
As React now sees that the type is different, it would not even try to update our node: old element will be removed (unmounted) together with all its children.
It is important to remember that React uses === (triple equals) to compare type values, so they have to be the same instances of the same class or the same function.
Scenario 4: type is a component.
// before update:
{ type: Table, props: { rows: rows } }
// after update:
{ type: Table, props: { rows: rows } }
“But nothing had changed!”, you might say, and you will be wrong.
If type is a reference to a function or a class (that is, your regular React component), and we started tree reconciliation process, then React will always try to look inside the component to make sure that the values returned on render did not change (sort of a precaution against side-effects). Rinse and repeat for each component down the tree—yes, with complicated renders that might become expensive too!
To make sure such things come clean:
class App extends React.Component {
state = {
change: true
}
handleChange = (event) => {
this.setState({change: !this.state.change})
}
render() {
const { change } = this.state
return(
<div>
<div>
<button onClick={this.handleChange}>Change</button>
</div>
{
change ?
<div>
This is div cause it's true
<h2>This is a h2 element in the div</h2>
</div> :
<p>
This is a p element cause it's false
<br />
<span>This is another paragraph in the false paragraph</span>
</p>
}
</div>
)
}
}
Children =============================>
we also need to account for React’s behavior when an element has more than one child. Let’s say we have such an element:
// ...
props: {
children: [
{ type: 'div' },
{ type: 'span' },
{ type: 'br' }
]
},
// ...
And we want to shuffle those children around:
// ...
props: {
children: [
{ type: 'span' },
{ type: 'div' },
{ type: 'br' }
]
},
// ...
What happens then?
If, while “diffing”, React sees any array inside props.children, it starts comparing elements in it with the ones in the array it saw before by looking at them in order: index 0 will be compared to index 0, index 1 to index 1, etc.
For each pair, React will apply the set of rules described above.
React has a built-in way to solve this problem. If an element has a key property, elements will be compared by a value of a key, not by index. As long as keys are unique, React will move elements around without removing them from DOM tree and then putting them back (a process known in React as mounting/unmounting).
So Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.
Because React relies on heuristics, if the assumptions behind them are not met, performance will suffer.
When state changes: =========================================>
Calling this.setState causes a re-render too, but not of the whole page, but only of a component itself and its children. Parents and siblings are spared. That is convenient when we have a large tree, and we want to redraw only a part of it.

Reconciliation in the context of React means to make React's virtual DOM tree consistent with the real DOM tree of your browser. This happens during (re-)rendering
The key point is that there is no guarantee that a specific element of React's virtual DOM refers to the same DOM node of your browser for its complete lifecycle. The reason for this is React's approach to update the DOM efficiently. You can use the special key property to solve this issue, if a component contains dynamic or stateful children.

Related

How to render a component inside async function in React

In my mongoDB I have documents with nested objects that corresponds to which make, model and year of the motorbike they fit to.
Example:
fits: {
honda: {
crf250: {
1990: true,
1991: true
},
rx400: {
2000: true
}
},
kawasaki: {
ninja: {
2015: true
}
}
}
I need to loop through all the makes that the document stores in fits field (In the example above it would be honda and kawasaki) and than return all the models that exist under the specific make. I am succesfully receiving the array of all the models under the make in my aggregate method.
return(
<ul style={{listStyleType: 'none'}}>
{Object.keys(props.data.fits).map((make, i) => {
if(db !== null && client !== null){
var query = `fits.${make}`;
var pipeline = [
{
$match: {
[query]: {
'$exists': true,
'$ne': {}
}
},
},
{
$group: {
_id: `$${query}`,
}
}
]
client.auth.loginWithCredential(new AnonymousCredential()).then((user) => {
db.collection('products').aggregate(pipeline).toArray().then((models)=>{
return <Make
style={{border: '1px solid grey'}}
mongoClient={props.mongoClient}
id={props.data._id}
key={i}
make={make}
data={props.data}
_handleDeleteMake={handleDeleteMake}
_updateRowData={props._updateRowData}
_models={models}
>
</Make>
}).catch(e=>console.log(e))
})
}
})}
</ul>
)
However after the call I need to render the makes. It should look something like this:
Next to the orange plus I want to show the list of all the other models that exists under the specific make so I don't have to repeat in writing the model again if its exists already and I can just click on it.
However rendering Make inside the async I am left with blank:
Now from what I understand is that the render finished before the async function finished that is why it simply renders empty list, but I don't really know how should I approach this problem. Any suggestions?
I don't think it's possible for you to render a React element in that async way. When React try to render your element that is inside the ul tags, because you are using async, at the time of DOM painting, there is nothing for React to render. Thus React render blank.
After the async is resolved, React won't re-render because React doesn't know that there is a new element being added in. Thus even when you actually have that element, since React doesn't re-render, you won't see that element in the app
Why does this happen? Because React only re-render when there are certain "signal" that tells React to re-render. Such is state change, props change, hooks call, etc. What you did doesn't fall into any of those categories, so React won't re-render. This is the same reason why you don't directly change the component state and instead must use method like setState to change it.

Backbone => React - Higher Order Components, inheritance and specialisation

I have a legacy Backbone app which I have begun to rewrite in React. The app has a main view containing two subviews, arranged vetically. The top panel displays some data, and the bottom one displays the result of some algorithm taking this data as input. Since I have many different data sources, each with a different algorithm applied to it, I have an abstract base View class, which I then subclass for each data source, adding, decorating and overriding methods as necessary. Somewhat like this:
// Base View.
const BaseView = Backbone.View.extend({
events: {},
initialize() {
this.subViewA = // instantiate subview...
this.subViewB = // instantiate subview...
},
generateResultData() {
// 'Abstract' method which should be specialised to generate data rendered by subViewB...
},
render() {
// render subviews...
},
});
// Derived View.
const Derived = BaseView.extend({
events: {
// event handlers...
},
add(a, b) {
return a+b;
},
// additional methods...
generateResultData() {
return {
result: this.add(2,2);
}
},
})
This results in a shallow hierarchy of many similar View classes. It's all terribly imperative, but it's a simple, intuitive and easy-to-reason-about pattern, and just works. I'm struggling to see how to achieve the same thing in React, however. Given that subclassing of subclasses of React.Component is considered an anti-pattern, my focus has naturally been on composition, and in particular Higher Order Components. HOCs (which I find beautiful, but unintuitive and often just downright confusing) seem to involve adding general features, rather than specialising/refining something more general. I have also considered passing in more specialised versions of Componenet methods through props. but that just means I have to use the same boilerplate Component definition over and over again:
// General functional component, renders the result of prop function 'foo'.
function GeneralComponent(props) {
const foo = this.props.foo || ()=>"foo";
return (
<div>
<span> { this.props.foo() } </span>
</div>
)
}
// Specialised component 1, overrides 'foo'.
class MySpecialisedComponent extends React.Component {
foo() {
return this.bar()
}
bar() {
return "bar"
}
render() {
return (
<GeneralComponent foo={this.foo} />
)
}
}
// Specialised component 2, overrides 'foo' and adds another method.
class MyOtherSpecialisedComponent extends React.Component {
foo() {
return this.bar() + this.bar()
}
bar() {
return "bar"
}
baz() {
return "baz"
}
render() {
return (
<GeneralComponent foo={this.foo} />
)
}
}
The above is a very simplistic case, obviously, but essentially captures what I need to do (though I would of course be manipulating state, which the example does not do, for simplicity). I mean, I could just do things like that. But I want to avoid having to repeat that boilerplate all over the place. So is there a simpler and more elegant way of doing this?
Generally, if a component is stateless and doesn't use lifecycle hooks, there are no reasons for it to be Component class. A class that acts as a namespace and doesn't hold state can be considered an antipattern in JavaScript.
In constrast to some other frameworks, React doesn't have templates that would need to map variables in order for them to be available in view, so the only place where bar function needs to be mentioned is the place where it's called. JSX is an extension over JavaScript, JSX expressions can use any names that are available in current scope. This allows to compose functions without any classes:
const getBar => "bar";
const getBaz => "baz";
const getBarBaz => getBar() + getBaz();
const MySpecialisedComponent = props => <GeneralComponent foo={getBar} />;
const MyOtherSpecialisedComponent = props => <GeneralComponent foo={getBarBaz} />;
An anonymous function could be passed as foo prop instead of creating getBarBaz but this is generally discouraged because of unnecessary overhead.
Also, default prop values could be assigned with defaultProps without creating new ()=>"foo" function on each component call:
function GeneralComponent({ foo }) {
return (
<div>
<span> {foo()} </span>
</div>
)
}
GeneralComponent.defaultProps = { foo: () => 'foo' };
IMO what is throwing you off isn't inheritance vs composition, it's your data flow:
For example, many of my derived views need to do custom rendering after the main render. I'm using a third-party SVG library, and the data rendered into the 'result' subview is derived from analysis of rendered SVG elements in the main data view above it
So what you're trying to do here is have a child update props of a distantly related component after render, correct? Like this?
// after the svg renders, parse it to get data
<div id="svg-container">
<svg data="foo" />
<svg data="bar />
</div>
// show parsed data from svg after you put it through your algos
<div id="result-container">
// data...
</div>
There's a lot of state management libraries out there that will help you with this problem, that is, generating data in one component and broadcasting it to a distantly related component. If you want to use a tool built-in to react to address this you may want to use context, which gives you a global store that you can provide to any component that wants to consume it.
In your example your child classes have data-specific methods (add, etc.). IMO it's more typical in react to have a generic class for displaying data and simply passing it down map functions as props in order to rearrange/transform the rendered data.
class AbstractDataMap extends PureComponent {
static defaultProps = {
data: [],
map: (obj, i) => (<div key={i}>{obj}</div>)
};
render() {
const { data, map, children } = this.props;
const mapped = data.map(map);
return (
<Fragment>
{mapped.map((obj, i) => (
children(obj, i)
))}
</Fragment>
);
}
}
// in some other container
class View extends Component {
render() {
return (
<div>
<AbstractDataMap data={[1, 2, 3]} map={(n) => ({ a: n, b: n + 1 })}>
{({ a, b }, i) => (<div key={i}>a: {a}, b: {b}</div>)}
</AbstractDataMap>
<AbstractDataMap data={[2, 4, 6]} map={(n) => (Math.pow(n, 2))}>
{(squared, i) => (<div key={i}>squared: {squared}</div>)}
</AbstractDataMap>
</div>
);
}
}
IMO this pattern of using an HOC to abstract away the labor of explicitly using .map in your render calls (among other uses) is the pattern you are looking for. However, as I stated above, the HOC pattern has nothing to do your main issue of shared data store across sibling components.
Answering my own question, which I've never donw before...
So my question really arose from a concern that I would need to refactor a large, imperative and stateful codebase so as to integrate with React’s composition-based model (also with Redux). But it occurred to me after reading the (very insightful and helpful) responses to my question that my app has two parallel parts: the UI, and an engine which runs the algorithms (actually it's a music analysis engine). And I can strip out the Backbone View layer to which the engine is connected quite easily. So, using React’s context API I've built an ‘AnalysisEngineProvider', which makes the engine available to subcomponents. The engine is all very imperative and classically object-oriented, and still uses Backbone models, but that makes no difference to the UI as the latter has no knowledge of its internals - which is how it should be (the models will likely be refactored out at some point too)...
The engine also has responsibility for rendering the SVG (not with BB views). But React doesn’t know anything about that. It just sees an empty div. I take a ref from the div and pass it to the engine so the latter knows where to render. Beyond that the engine and the UI have little contact - the divs are never updated from React state changes at all (other components of the UI are though, obviously). The models in the engine only ever trigger updates to the SVG, which React knows nothing about.
I am satisfied with this approach, at least for now - even if it's only part of an incremental refactor towards a fully React solution. It feels like the right design for the app whatever framework I happened to be using.

React best practise / using parent component instance

let's imagine data that would look like that :
{
{
title: "great track",
tags: ["techno"]
},
{
title: "superb track",
tags: ["house", "90s"]
},
...
}
I render that in an html table, I have a component for the whole table, and a sub component for the tr (aka song title and tracks). so on each line I want to allow the users to be able to access a popup in which they can choose one or more tags for a song. I did it using reactstrap, it works ok.
I'm just a little disappointed by performance, it's quite ok, once it's built, but I saw how much longer it was to load when I added my modal on each line. So my first reflex, was to built only one modal in the parent component, and then use it from the sub component, and then I read articles on how, "one should not use the parent instance because it's bad"(tm).
I understand the point about dataflow, but in my example, having a modal waiting on each line while I'm sure I will never have two at the same time on screen feels like a waste of ressources.
Can anyone point me to an elegant way of building that kind of feature, in this particular context ?
Lifting state up to the parent component is a common practice in react, you can read articles in official documentation https://reactjs.org/docs/lifting-state-up.html
But there is one problem, when you use setState in your parent component, your songs table will render again and again, so you should care about it. One of the way is creating PureComponent for Songs table(if there is no changing in props, this component will not rerender)
I think, the code below is one of the way;
class Parent extends React.Component{
state={
tags: [],
songs: {
title: "great track",
tags: ["techno"]
},
{
title: "superb track",
tags: ["house", "90s"]
}
}
handlePopup(data){
this.setState({tags: data});
}
render(){
const {tags, songs} = this.state;
cons isShowModal = tags && tags.length
return (
<div>
{isShowModal && <Modal data={tags} />}
<SongsList data={songs} />
</div>
)
}
}
class Parent extends React.PureComponent{
render(){
const {data} = this.props;
return (
<table><tbody>...render songs data</tbody></table>
)
}
}
Of course using modal in child rows is a waste of resources. you need to add a modal to parent and use props to show/hide it. also, you should use the key prop for your list items.
By default, when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever there’s a difference.
but when children have keys, React uses the key to match children in the original tree with children in the subsequent tree.
it's good for performance.

Immutability is an implementation detail in React?

I recently watched a talk by David Nolen where he says that 'immutability is an implementation detail in React'?
What does this mean and if this wasn't the case, how would React be different?
What does "implementation detail" mean:
I would summarize as:
Immutability is a detail of react that you have to implement yourself.
BTW: "Detail" is this case can still mean a lot of work.
React depends on props and state to be immutable.
React does not make props or state immutable for you. You have to ensure that in your code yourself.
So the following code is a recipe for disaster:
// DO NOT TRY THIS AT HOME
var customerObject = { name: "Bill" };
this.setState( customer: customerObject }; // valid react code, triggering re-render
...
customerObject.name = "Karl";
// state still has the same customerObject,
// but the contents of the object have changed. This is where things break down.
React has to ensure that its internal virtual DOM, and all props and states, are always in sync with the actual DOM.
So every time something changes anywhere in a prop or state, react needs to run its render cycle.
How would react be different without immutability:
Without immutability your react implementation may not work properly.
If react were not designed for immutability, then it would not be react (i.e. a state machine) but a different beast altogether.
Immutable Data Structure with ReactJS
The first of all, react team strongly recommend applying immutable data structure like Immutability Helpers or immutable.js. Why? Because we can use "shallow comparison" to increase component re-render performance. like
MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState);
}
render() {
...
}
}
According to immutability, the data alway return a new reference if it has been changed. We can easy use shallowEqual(only check reference whether is same or not) to determine component will re-render. If we dont use immutable data, we have to check props or state object deeply not reference to make sure re-rendering.
As for my understanding, each component in React has its own standalone scope and they don't share the variables.
That means when you pass an mutable variable(such as Object or Array) through props to a specific react component. It will clone each variable so that this component will have a totally new environment.
For example, assuming you have component A, and it works like this,
var ComponentA = React.createClass({
render: function() {
var user = { name: 'Tyler', role: 'Developer' };
return (
<SubComponent user={user} />
);
}
});
What ComponentA wants is simply render the user. So it require another module, let's say SubComponent to do that.
var SubComponent = React.createClass({
render: function() {
return (
<div>
<span>Name: {this.props.user.name}</span>
<span>Role: {this.props.user.role}</span>
</div>
);
}
});
For now, we should notice the variable user in ComponentA is different with the variable this.props.user in SubComponent. The this.props.user is not a reference. It's cloned from the ComponentA.
So that means, when you try to change the value of this.props.user in SubComponent, it won't destroy the user in ComponentA. Which is what David Nolen said in his tech talk. ("Change something in data without destroy the old one.")
Of course this would sacrifice some extra spaces, but you can get lots of benefits. Such as each of your component would be totally separated. Then all the nightmares cause by Shared Mutable Variables are gone. Shared Mutable Data is the root of evil, it's unpredictable and unreliable.
Imagine the SubComponent and the ComponentA are share the same user and you want to render another module by passing props user. Then you will update your code into this way,
var ComponentA = React.createClass({
render: function() {
var user = { name: 'Tyler', role: 'Developer' };
return (
<div>
<AnotherComponent user={user} />
<SubComponent user={user} />
</div>
);
}
});
Once we change the name of user in SubComponent(maybe by accident), we will have a cascading effect, and we don't know which one change the variable. That's painful coz then we have to check each line of the code in SubComponent and AnotherComponent. You really don't want to do that, right?
So I think that's what he mean. Hope this can solve your problem. : )

How to use the component string returned from server in React via AJAX

All:
I am pretty new to React, I am trying to render a component from the string return by Server side ReactDomServer.renderToString(), could anyone give me a working patrn or example to do this in AJAX?
A case will be:
One the init page, there is a dropdown, you choose different type of componnet, then it will submit AJAX request to server, then server return according string, then the page will render that component on it.
Thanks
From the comments on your question, it sounds like what you're looking to do is dynamically render a UI.
Your request was for an example of a drag-and-drop rendering workflow, but that would stray too far from your question. It's important that we first tease out the many components and then focus on the one that's interesting for this question. We have a data layer and server-side responsible for storing information, business logic for determining how components should render where and when, interaction paradigms like drag and drop that work within these rules, and the rendering of components based on them.
All of these are separate concerns that must be considered independently. For example, drag and drop is one way to add components, but it is likely to not be the only way, so why couple the two? That leaves us with just rendering dynamic components, which I shall consider here. I'll be using ES2015 syntax to make the code cleaner.
First, we have a main component that does the wrapping:
const Renderer = React.createClass({
render () {
// ...
},
});
ReactDOM.render(
<Renderer layout={layout} />,
document.getElementById( 'app' )
);
Now let's consider the components you mentioned, which will be pure:
const Button = ({ text }) => (
<button>{text}</button>
);
const Input = ({ type = "text", placeholder }) => (
<input type={type} placeholder={placeholder} />
);
And some container for available components (which would likely also have metadata and rules about each):
const Components = {
Button,
Input,
};
And now let's assume we have a configuration defined in json:
{
"name": "My Interface",
"layout": [
{ "id": 123, "component": "Input", "placeholder": "keywords..." },
{ "id": 456, "component": "Button", "value": "Search!" },
],
}
This is highly simplified, but you can imagine this document showing all properties for a deeply nested UI, perhaps sporting different types of containers like rows and columns. Now we can assume the JSON property layout is the layout property passed to the Renderer above. Now our render function can look like this (highly simplified):
render () {
const children = this.props.layout.map( ({ component, ...props }) => {
const Component = Components[ component ];
return <Component {...props} />
});
return (
<div className="component-view">
{children}
</div>
);
}
Whenever the model changes, we would re-render the component tree and see what we should. There is a lot that would have to go into something like this to get a full UI editor - that's a massive undertaking. But with proper design principles and separation of concerns, it's at least doable.
To return to drag and drop briefly, if we were to drag and drop, we would note its place and insert the component into the tree however made sense based on the component and the state of the item onto which it's dropped, etc. The result of the operation, assuming it was successful, would be a mutated layout tree, which triggers a re-render.
Note: I completely ignored performance considerations.

Resources