Video Tutorial Create your own React


In this video I propose to decrypt the operation of React through the creation of a similar library. The goal is to better understand the operation of virtual dom and the mechanics behind the reactivity of the components.

This article follows the article published by Rodrigo Pombo (some modifications have been made to the code to correct some problems).

The different steps

Step 1: The createElement function

When using the JSX syntax the code is automatically transformed by tools like babel. So when we write:

return 
Hello world

The code is translated into:

return React.createElement ('div', {class: 'demo'},
  'Hello',
  React.createElement ('strong', {}, 'World')
)

This method will convert our elements into an object so that we can then process them in the function render ()

Step 2: The render function

When we want to insert an element in our DOM we use the function render () of ReactDOM. A first implementation of this function is to read our tree by adding elements to the DOM recursively.

Step 3: The competing method

The problem of the recursive approach developed in step 2 is that it completely blocks the browser during the processing of the tree. In the case of a tree, this can have a negative impact on the user experience because the interface is completely blocked during processing.

To remedy this problem we use a planner which allows to treat our tree node by node while allowing an external process to be interposed (the navigator can thus manage other operations at the same time as the generation of the DOM). The use of a planner involves being able to break up the tree processing into a unit of work that can determine the next operation to be performed.

Step 4: Fibers

For the system to work you have to determine a rule to browse our tree. Operation is as follows

  • Once a node is processed, we treat the child node
  • If no child node exists, treat the neighbor node
  • If no neighbor node exists, go back to the parent's neighbor
  • If the parent does not have a neighbor, we continue to go back to the parent's neighbor

For each treated node we will generate a property that will contain the DOM generated for the node in question.

Step 5: Render and Commit

In order to optimize the performance on the browser side, we will not add the elements to the DOM before the end of the tree processing. So we'll add a phase of commit which will traverse our tree and which will link all elements of the DOM via appendChild.

Step 6: Reconciliation

Until now the code is only able to add elements. We will therefore set up a reconciliation step that will compare the old nodes to the new ones in order to detect the changes to be made (Addition, Modification or Deletion of the element).

To make this comparison we will save the old tree "Fibers" and we will run in parallel when we generate our new tree.

  • If the 2 elements have the same type, then we will modify the attributes / events.
  • If the two elements do not have the same type then we will delete the old one and add the new one.
  • If an element is present in the old tree, but not in the new one it is deleted.
  • Conversely, if an element does not exist in the old tree, it is simply added.

Step 7: Functional component

The management of a component as a function is relatively easy (compared to the rest) because it is enough to execute the function to obtain its structure. On the other hand, adaptations will have to be made to manage elements that will not necessarily exist in the DOM.

Step 8: The hooks

To create a hook we will create a method useState () which will add a hook to our component in a property hooks. Just like for React the hook call order should not change because the index is retrieving the reference when a new rendering is done.