Until now, we've covered mounting, the React element tree, etc. They are parts of the foundations of React. Another important concept, is the React component class. It's only by extending the React.Component, can you take advantage of the setState function and the life cycle hooks built inside React. So in this post, we are gonna cover three sub-topics:
how the component class gets rendered
setState
life cycle hooks
How the Component Class Gets Mounted and Rendered
When you create a class and have it extend from React.Component, there is no difference from extending a normal parent class. You just extend a lot of parent methods, of which are render, setState, and the life cycle hooks.
As we know, a react component class requires at least a render method. So, we could start from here:
class Component {
constructor(props) {
if (!this.render) {
throw Error('a component class must at least have a render method')
}
this.props = props
}
}
Now we should add a mountComponent method so that it could be rendered to the screen the first time. But inside mountComponent, we're gonna call a method recursively (this method is very similar as mount, except it doesn't append to a node directly but return the markup of the element tree, we'll come back later) until the tree is all about native DOM nodes.
The method mountComponent in the class should be:
mountComponent() {
let renderedElement = this.render();
// assume the wrapper is also a component class for now
let renderedComponent = new renderedElement.type();
return renderedComponent
}
Now we could update the mountComposite function as:
function mountComposite(component, type) {
let componentNode;
if (isClass(component.type)) {
const component = new component.type(component.props)
componentNode = component.mountComponent()
} else {
componentNode = component.type(component.props)
}
// delegate to mount one level deeper
mount(componentNode, node)
}
Now, we are able to support 4 types of react components in the mounting process, which are:
text node
native DOM node
function component
class component
Refactor and Decouple
Let's re-think about the mounting process.
We call mount in this way:
mount(<App />, document.querySelector('#root'))
The first argument it takes is an element object, if you still remember what createElement works. And it finally use this element to create the according component, and then generate the real DOM node and append it to '#root'. It could be be separated into the following sub-processes:
element object => component => real DOM node
When creating the according component, we use the if statement to judge what kinds of component it is. But on second thought though, on a very high level like mount, we should use as few as function polymorphism and if statement as possible, but create a generic class for each of them and expose the same method API like initiateComponent, and mountComponent. So before moving on, let's do some refactoring.
We want to create a separate class for each type of the components, and let themselves take charge of creating their corresponding DOM node, so that the polymorphism becomes class-based, and the flow more clear:
Until now, we've covered mounting, the React element tree, etc. They are parts of the foundations of React. Another important concept, is the React component class. It's only by extending the
React.Component
, can you take advantage of thesetState
function and the life cycle hooks built inside React. So in this post, we are gonna cover three sub-topics:How the Component Class Gets Mounted and Rendered
When you create a class and have it extend from
React.Component
, there is no difference from extending a normal parent class. You just extend a lot of parent methods, of which arerender
,setState
, and the life cycle hooks.As we know, a react component class requires at least a
render
method. So, we could start from here:Now we should add a
mountComponent
method so that it could be rendered to the screen the first time. But insidemountComponent
, we're gonna call a method recursively (this method is very similar asmount
, except it doesn't append to a node directly but return the markup of the element tree, we'll come back later) until the tree is all about native DOM nodes.The method
mountComponent
in the class should be:Now we could update the
mountComposite
function as:Now, we are able to support 4 types of react components in the mounting process, which are:
Refactor and Decouple
Let's re-think about the mounting process.
We call
mount
in this way:The first argument it takes is an element object, if you still remember what
createElement
works. And it finally use this element to create the according component, and then generate the real DOM node and append it to '#root'. It could be be separated into the following sub-processes:When creating the according component, we use the if statement to judge what kinds of component it is. But on second thought though, on a very high level like
mount
, we should use as few as function polymorphism and if statement as possible, but create a generic class for each of them and expose the same method API likeinitiateComponent
, andmountComponent
. So before moving on, let's do some refactoring.We want to create a separate class for each type of the components, and let themselves take charge of creating their corresponding DOM node, so that the polymorphism becomes class-based, and the flow more clear: