primers

Someone asked me today, when we were working on the React project, why was the suffix.jsx? I was stunned for a moment, not. JSX, can also be. TSX ah, you ask what this mean. He went on to say, “We’re writing js files, so why don’t I just use the.js suffix instead of the filename suffix?”

What is the essence of JSX and how is it different from JS

As a React user, it is your daily job to use JSX to describe React component content. We all know that JSX is React’s user-friendly syntactic sugar for writing components, but how is it different from JS?

The essence of JSX is a syntactic extension of JS

JSX is a syntax extension to JavaScript. It is similar to a template language, but it has full power of JavaScript.

Since JSX is an extension of JS syntax, it must be that there are some functions in original JS that can’t be customized by React tool, or for user experience, we need to do some extension packaging in native JS to make it more enjoyable for users to use. According to the React official introduction, I think a better user experience and less code is probably the more important reason to use JSX.

JSX gets compiled to React. CreateElement () calls which return plain JavaScript objects called “React elements”.

JSX is compiled into an object called ReactElement, which is the true owner of the description component. So, instead of JSX, we can write the component directly using React. CreateElement (), which saves a layer of Babel transformation.

But our component is so complex that it requires more attributes when using object descriptions. The deeper the hierarchy, the more nested the code, and the less readable it becomes. At this time in the face of excrement mountain level code, may directly dissuade. React, in order to retain users, leaves the difficulty to itself and the smoothness to the users, and lets people write components using attribute class HTML as much as possible. As for the complicated processing, let React suffer silently.

Tip: This is why all components prior to React17 must incorporate React, even if you don’t explicitly use React, because your JSX files require the React.createElement() method, which is used during compilation. Babel did it for you, but when you introduce React, you get an error. React 17 solves this problem, of course. Whenever an Entry is used in the React root path, the following components will handle it automatically

This explains why we use.jsx as the suffix when we write React components, because we need to flag Babel and tell it that we need to compile. You don’t have to, of course, you can, because Babel is such a great tool, even if you don’t tell it, it can find out that you’re a React component based on the code you’re writing. You’re writing JSX, you need to compile it into ReactElement, and then service you. But if you don’t, it’s not readable enough to distinguish between a regular JS file and a JSX component, and it does have some effect on the compilation.

Some questions are not can, is not elegant. A lot of the code is usable and not too problematic, but it’s just gross, uncomfortable and inelegant. For example, is React synchronous or asynchronous? This is a typical question for the sake of asking. I really want to ask you a question, when have you used it to synchronize situations? Talk about that next time.

How does JSX map to DOM

The React. The createElement method () the source code

export function createElement(type, config, children) {
  let propName;

  // Store element attributes
  const props = {};

  // There are several special properties that require additional variables to hold
  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if(config ! = =null) {
    if (hasValidRef(config)) {
      ref = config.ref;
    }
    if (hasValidKey(config)) {
      key = "" + config.key; // Convert to a string
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;

    for (propName in config) {
      if (
        // Filters attributes that can be placed in propshasOwnProperty.call(config, propName) && ! RESERVED_PROPS.hasOwnProperty(propName) ) { props[propName] = config[propName]; }}}// The first two input parameters are type and config, and the rest are children
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    // If there is only one child, assign it directly to props
    props.children = children;
  } else if (childrenLength > 1) {
    // If there are multiple children, return an array of children
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    props.children = childArray;
  }

  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (let propName in defaultProps) {
      if (props[propName] === undefined) { props[propName] = defaultProps[propName]; }}}return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props
  );
}
Copy the code

Analysis of the reference

Babel converts JSX to React. CreateElement (Type, Config,children),

  • Type: for arguments that are not of the node type; Can beh1.divThe type of hostCompoennt can also be ReactComponent
  • Config: All properties in the component are entered as config objects, including special properties such as key, ref, className,xxxThis kind of custom property
  • Children: child elements, child nodes, are nested in the form of objects, which also contain the type, config, and children attributes.

Example:


var element = React.createElement(
  "h1",
  {
    xxx: "111".ref: "myDiv",
  },
  React.createElement(
    "p",
    {
      yyy: "222",},"123"));Copy the code

Corresponding to the DOM

  <h1 xxx="111" ref="myDiv">
    <p yyy="222">123</p>
  </h1>
Copy the code

The process of disassembling createElement

  1. Entry React. CreateElement — in the React /ReactElement file
  2. The special properties are handled twice: ref, key, self, source
    • Ref (props) : props (props) : props (props) : props
  3. Walk through the config to filter out attributes that can be extracted into props
    • All properties are stored in props except for the four special properties and the properties inherited from the prototype chain
  4. Extract the child element and add it to props. Children
    • It can be a single children object or an array of objects
  5. Formatting defaultProps
  6. Combined with the above parameters, it is formatted again with ReactElement, and then it becomes a ReactElement object.

Connect the virtual DOM to the real DOM

  • The last thing createElement returns is the virtual DOM tree, which is a mapping of the real DOM
  • On the Web, we usually use React. Render (element,root) to map the virtual DOM to the real DOM

summary

  • JSX is created to simplify the syntax-sugar creation of ReactElement. The native JSX is not recognized by the browser and needs to be compiled into the React. CreateElement (Type, Config,children) form by Babel. And is finally represented as a ReactElement object
  • ReactElement is actually the so-called virtual DOM, and the root node is actually the virtual DOM tree, because it is a tree structure, and it is the mapping of the real DOM
  • In the Web, we usually use React. Render to map the ReactElement to the real DOM, where the input requires a container DOM node
  • The use of the.jsx suffix mentioned in the introduction is for the sake of code specification and easy reading. The second is to prompt Babel compilation.
  • After React 17, it was possible to write JSX directly without introducing React, without fear that Babel would not be able to report errors.