Hello, everyone. I am Karsong.

React can be seen as a combination of three parts:

  • Scheduler is used to schedule tasks

  • Reconciler, a reconciler, is used to calculate the side effects caused by tasks

  • The renderer, the renderer, is used to perform side effects in the host environment

These three are independent packages, and the ReactDOM introduced in our project can be seen as a package of the following three parts of code:

  • Scheduler’s main logic

  • Reconciler is a partial logic

  • The ReactDOM renderer’s main logic

This article will teach you how to implement a mini-ReactDOM based on the official Reconciler.

This article refers to the Hello World Custom React Renderer

Project initialization

Establish projects through CRA (or with existing projects) :

create-react-app xxx
Copy the code

Create a new CustomRenderer.js, introduce the React-Reconciler and complete the initialization:

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

const hostConfig = {};
const ReactReconcilerInst = ReactReconciler(hostConfig);
Copy the code

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); }};Copy the code

In the project entry file, replace the ReactDOM with our CustomRenderer implementation:

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

/ / replace ReactDOM
CustomRenderer.render(
  <App />.document.getElementById('root'));Copy the code

Implement ReactDOM

Next we implement the hostConfig configuration, first fill 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(){}}Copy the code

Note that the only configuration item here of type Boolean supportsMutation indicates that the host environment API supportsMutation.

This is how DOM apis like Element.appendChild and Element.removechild work. It doesn’t work this way in Native environments.

Let’s implement these apis.

Implement the API

These apis fall into the following categories.

Example Initialize the environment information

GetRootHostContext and getChildHostContext are used to initialize context information.

Generating DOM nodes

  • CreateInstance is used to create a DOM node

  • CreateTextInstance creates a text node

We can implement createTextInstance as follows:

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

Judgment of key logic

ShouldSetTextContent shouldSetTextContent is used to determine if children of the component are text nodes.

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

DOM manipulation

AppendInitialChild is used to insert a DOM node as follows:

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

CommitTextUpdate is used to change text nodes as follows:

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

RemoveChild is used to removeChild nodes as follows:

removeChild(parentInstance, child) {
  parentInstance.removeChild(child);
}
Copy the code

When all apis are implemented, the page should render normally:

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

conclusion

After learning this article, we have implemented a simple ReactDOM.

If you want to use React in any environment where you can draw the UI, you can implement React in that environment with the React-Reconciler.

For example, Introduction To React Native Renderers teaches you how To implement React in a Native environment.

Welcome to join the Human high quality front-end framework research group, Band fly