Build a ReactDOM yourself

Hello, I'm Carson.

React can be seen as a combination of three parts:

  • Scheduler, scheduler, used to schedule tasks
  • reconciler, coordinator, used to calculate the side effects caused by tasks
  • Renderer, a renderer that performs side effects in the host environment

These three packages are independent. The ReactDOM introduced in our project can be regarded as the following three parts of code packaged:

  • Main logic of scheduler
  • reconciler partial logic
  • Main logic of ReactDOM renderer

This article will teach you how to implement Mini react DOM based on the official reconciler.

Article reference Hello World Custom React Renderer

Project initialization

Establish projects through CRA (or use existing projects):

create-react-app xxx

Create a new customRenderer.js, introduce react reconciler and complete initialization:

// The reconciler version used in this article is 0.26.2
import ReactReconciler from 'react-reconciler';

const hostConfig = {};
const ReactReconcilerInst = ReactReconciler(hostConfig);

hostConfig is the configuration item of the host environment.

Finally, customRenderer.js exports an object containing the render method:

export default {
  render: (reactElement, domElement, callback) => {
    // Create root node
    if (!domElement._rootContainer) {
      domElement._rootContainer = ReactReconcilerInst.createContainer(domElement, false);
    }

    return ReactReconcilerInst.updateContainer(reactElement, domElement._rootContainer, null, callback);
  }
};

In the project entry file, replace ReactDOM with the CustomRenderer we implemented:

import ReactDOM from 'react-dom';
import CustomRenderer from './customRenderer';

// Replace ReactDOM
CustomRenderer.render(
  <App />,
  document.getElementById('root')
);

Implement ReactDOM

Next, we implement the hostConfig configuration. First, fill in the empty function to avoid application error:

const hostConfig = {
  supportsMutation: true,
  getRootHostContext() {},
  getChildHostContext() {},
  prepareForCommit() {},
  resetAfterCommit() {},
  shouldSetTextContent() {},
  createInstance() {},
  createTextInstance() {},
  appendInitialChild() {},
  finalizeInitialChildren() {},
  clearContainer() {},
  appendInitialChild() {},
  appendChild() {},
  appendChildToContainer() {},
  prepareUpdate() {},
  commitUpdate() {},
  commitTextUpdate() {},
  removeChild() {}
}

Note that the only configuration item of Boolean type here is supportsMutation, which indicates that the API of the host environment supports mutation.

This is how DOM API s work, such as element.appendChild and element.removeChild. This is not the case with Native environments.

Next, let's implement these API s.

Implementation API

These API s can be divided into the following categories.

Initialize environment information

getRootHostContext and getChildHostContext are used to initialize context information.

Generate DOM node

  • createInstance is used to create DOM nodes
  • createTextInstance is used to create a text node

createTextInstance can be implemented as follows:

createTextInstance: (text) => {
  return document.createTextNode(text);
}

Judgment of key logic

shouldSetTextContent is used to judge whether the children of the component are text nodes. The implementation is as follows:

shouldSetTextContent: (_, props) => {
    return typeof props.children === 'string' || typeof props.children === 'number';
},

DOM operation

appendInitialChild is used to insert DOM nodes. The implementation is as follows:

appendInitialChild: (parent, child) => {
  parent.appendChild(child);
},

commitTextUpdate is used to change the text node. The implementation is as follows:

commitTextUpdate(textInstance, oldText, newText) {
  textInstance.text = newText;
},

removeChild is used to delete child nodes. The implementation is as follows:

removeChild(parentInstance, child) {
  parentInstance.removeChild(child);
}

When all API s are implemented, the page can be rendered normally:

For the Demo address of the complete implementation, see: Full Demo address

summary

After the study of this article, we have implemented a simple ReactDOM.

If you want to use React in any environment that can draw UI, you can use React reconciler to realize React in that environment.

For example, Introduction To React Native Renderers Teach you how to implement React in Native environment.

Welcome to join Human high quality front-end framework group , with flying

Tags: Javascript Front-end React

Posted on Mon, 22 Nov 2021 20:44:09 -0500 by daboymac