react source code analysis 5.jsx & Core api

Keywords: React

react source code analysis 5. JSX & Core api

Video Explanation (efficient learning): Enter learning

Previous articles:

1. Introduction and interview questions

2. Design concept of react

3.react source code architecture

4. Source directory structure and debugging

5. JSX & Core api

6.legacy and concurrent mode entry functions

7.Fiber architecture

8.render stage

9.diff algorithm

10.commit phase

11. Life cycle

12. Status update process

13.hooks source code

14. Handwritten hooks

15.scheduler&Lane

16.concurrent mode

17.context

18 event system

19. Handwritten Mini react

20. Summary & answers to interview questions in Chapter 1

What is virtual Dom

In a word, the dom information and structure are represented by js objects. When updating, the dom corresponding to the updated object is re rendered. This object is the return result of React.createElement()

virtual Dom is a programming method. It is stored in memory in the form of objects. It describes the necessary information of our Dom and synchronizes with the real DOM with modules such as react dom. This process is also called reconciler. This method can declaratively render the corresponding ui state and liberate us from DOM operations, In react, the relevant information of the component tree is stored in the form of fiber tree. When updating, the relevant DOM can be rendered incrementally, so fiber is also a part of the implementation of virtual Dom

Why use virtual Dom

A large number of dom operations are slow, and small updates may cause page rearrangement. js objects are better than in memory and can be processed faster. You can compare the differences between new and old virtual DOMS through diff algorithm, and perform dom changes in batch, asynchronous and minimized to improve performance

In addition, it can cross platform, JSX -- > reactelement object -- > Real node. If there is an intermediate layer, the corresponding processing can be carried out before operating the real node, and the processing results are reflected on the real node. The real node can be a browser environment or a Native environment

Is virtual Dom really fast? In fact, virtual Dom is only fast when updating, but not necessarily fast at the beginning of the application

const div = document.createElement('div');
let str = ''
for(let k in div){
  str+=','+k
}
console.log(str)

jsx&createElement

jsx can declaratively describe views and improve development efficiency. It can be converted into the syntax sugar of React.createElement() through babel, which is also an extension of js syntax.

jsx is the render function of ClassComponent or the return value of FunctionComponent. It can be used to represent the content of the component. After babel compilation, it will be compiled into React.createElement. That's why the jsx file declares import React from 'react' (you don't need to import it after react17). You can view the compiled results of jsx on the site

The source code of React.createElement does the following things

  • Process config and assign other config values except reserved attributes to props
  • Assign children to props.children after processing
  • Processing defaultProps
  • Calling ReactElement returns a jsx object (virtual DOM)
//ReactElement.js
export function createElement(type, config, children) {
  let propName;

  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    //Process config and assign other config values except reserved attributes to props
    //...
  }

  const childrenLength = arguments.length - 2;
  //Assign children to props.children after processing
  //...

  //Processing defaultProps
  //...

  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    $$typeof: REACT_ELEMENT_TYPE,//Represents a ReactElement type

    type: type,//class or function
    key: key,//key
    ref: ref,//ref attribute
    props: props,//props
    _owner: owner,
  };

  return element;
};

$$typeof represents the type of component. For example, there is a function in the source code to check whether it is a legal Element, that is, the root object.$$typeof === REACT_ELEMENT_TYPE

//ReactElement.js
export function isValidElement(object) {
  return (
    typeof object === 'object' &&
    object !== null &&
    object.$$typeof === REACT_ELEMENT_TYPE
  );
}

If the component is ClassComponent, the type is the class itself. If the component is created by FunctionComponent, the type is this function. ClassComponent.prototype.isReactComponent is used in the source code to distinguish the two. Note that components created by class or function must be capitalized first, and then treated as ordinary nodes. Type is a string.

There are no priority, status, effectTag and other tags on the jsx object. These tags are on the Fiber object. During mount, the Fiber is built according to the jsx object. During update, a new workInProgress Fiber is formed according to the comparison between the latest jsx and current Fiber. Finally, the workInProgress Fiber is switched to current Fiber.

render

//ReactDOMLegacy.js
export function render(
  element: React$Element<any>,//jsx object
  container: Container,//Mount dom
  callback: ?Function,//Callback
) {
  
  return legacyRenderSubtreeIntoContainer(
    null,
    element,
    container,
    false,
    callback,
  );
}

You can see what render does, that is, it calls legacyRenderSubtreeIntoContainer. This function will be explained in the next chapter. Here we focus on the three parameters used by ReactDom.render().

component

//ReactBaseClasses.js
function Component(props, context, updater) {
  this.props = props;//props attribute
  this.context = context;//Current context
  this.refs = emptyObject;//ref mounted object
  this.updater = updater || ReactNoopUpdateQueue;//Updated object
}

Component.prototype.isReactComponent = {};//Indicates classComponent

In the component function, props, context, refs, updater, etc. are mainly mounted on the current instance, so these can be obtained on the component instance. The main bearer structure of update is updater, which mainly focuses on isReactComponent, which is used to indicate that this component is a class component

Summary: jsx is the syntax sugar of React.createElement. jsx is transformed into React.createElement function through babel. After the execution of React.createElement, jsx object, also known as virtual DOM, is returned. Fiber will compare jsx object with current Fiber to form workInProgress Fiber

pureComponent is also very simple, similar to component. It will inherit the prototype and assign isPureReactComponent

function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

export {Component, PureComponent};

Posted by misc00500 on Fri, 03 Dec 2021 17:48:38 -0800