[Recognize the front end] React source code reading (1) What is jsx

[Recognize the front end] React source code reading (1) What is jsx

Preface

Some nonsense and personal feelings, just skip it if you look at the dry goods... to

jsx

It's been more than half a year since I re-understood the intermittent front end. It is basically the accumulation of personal technology stack and the answers to interview questions. Interested partners can click on my homepage to see.

Talk about today's protagonist-

React
Right.
React
I ve always wanted to read and study the source code of .I have really read it, but I often get sleepy when I look at it. Then I started to be lazy and read from some surroundings, such as
React-Router
,
React-Redux
some type of. Before I started writing articles after reading it. Now I want to write while reading, and look at it in another way. If there is any mistake, you are welcome to discuss it. If you think it is okay, you can like it, thank you!

as a

React
Heavy users and enthusiasts. I will work with you to progress from "user" to "understander"!

React related information

Utilitarian perspective

Open the recruitment software, now basically big factories and even outsourcing companies generally require you to

React
or
Vue
. The salary given is also very attractive.

(The picture is from a boss of Boss)

In order to make a fortune, this simple dream should also be studied.

Learning perspective

Now three front-end companies:

Angular
,
React
,
Vue
One-third of the world. Favored more domestically
React
with
Vue
. Therefore, we should learn more from the perspective of learning
React
.

www.npmtrends.com/react-vs-vu...

Why have to learn source code

I have asked this question before. Almost all interviews are about building rockets and screwing the screws at work.

I think the problem is viewed from two perspectives:

  1. Applicants
    1. Eat thoroughly
      React
      In the case of, the upper limit of solving the problem must be increased
    2. An excellent framework is an excellent teacher
  2. Recruiters, since they are all able to do the job, I will find someone who knows more to do this job

JSX

Don't talk nonsense, just start.

JSX, can't be more familiar, I will definitely use it in the daily use of React. Give a demo to help everyone get back.

import React from "react"; import ReactDOM from "react-dom"; class App extends React.Component { render() { const text = "hahaha" return ( <div> <p>{text}</p> </div> ); } } const rootElement = document.getElementById("root"); ReactDOM.render(<App/>, rootElement); Copy code

Let me ask a few questions first. If I can answer them clearly and quickly, congratulations, you have a solid foundation. If not, then take a look together. After reading, you can write your answers in the comment area and discuss with you. .

  • what is
    JSX
    ?
    JSX
    with
    JS
    what is the relationship?
  • JSX
    What is the underlying principle?
  • why
    React
    To choose
    JSX
    ?

Let's look at it with questions.

What is JSX

First look

React
A word on the official website.

const element = <h1>Hello, world!</h1>; Copy code

It is called JSX and is a syntax extension of JavaScript.

Syntax expansion, meaning

JS
In some cases he has, there are some other functions. But this one is obviously
JavaScript
I haven't seen him in the process of studying. He can run on
JavaScript
Environment? turn on
Chrome
Console.

The grammatical error that came up was hacking. It seems that this part is an extra function. How does it work?

{ test : /\.(js|jsx)?$/ , //enable caching options: { cacheDirectory : true }, loader : 'babel-loader' , }, Copy code

How is it, is it familiar or not, it means telling

webpack
, Parse
jsx
The code at the end, you need to use
babel
. ok, which means to run
jsx
, You must use
babel
Parsing. Okay, what is babel?

babel

Pull a section

babel
A sentence on the official website

Babel is a JavaScript compiler

Babel is a tool chain, mainly used to convert ECMAScript 2015+ version code into backward compatible JavaScript syntax so that it can run in current and old versions of browsers or other environments.

babel
, In fact, is to help us parse the code we wrote, and then become the browser can recognize the style. such as
jsx
, Such as fresh
es6
The syntax can be run on the old version of the browser, so that the old version of the browser can recognize it.

The question comes again, what has jsx been like by babel?

Online conversion: babeljs.io/repl

You can throw in the small demo above.

Not found. we

return
What went out became
React.createElement
. Haha, that s why we don t use
React
(Solved the first interview question!), also need to be on it
import
,because
jsx
In the end it will be transformed into
React.createElement
, Will be used! (However, it seems that the latest one does not need to be quoted and will not report an error, because he has identified it himself.

Official website introduction: zh-hans.reactjs.org/blog/2020/0...

//Introduced by the compiler (importing by yourself is prohibited!) import {jsx as _jsx} from'react/jsx-runtime'; function App() { return _jsx('h1', {children:'Hello world' }); } Copy code

Note that at this time, the source code can use JSX without introducing React ! (However, React still needs to be introduced in order to use Hooks or other exports provided by React.)

Back to before

React
Mentioned on the official website

It is called JSX and is a syntax extension of JavaScript.

Has it echoed, indeed

js
He has it, but
js
No, he has for example transformed into
React.createElement
.

createElement

We are here to read the source code to learn, now that we know

jsx
The bottom layer is to call
react
Function, let s take a look at what this function is like.

export function createElement ( type, config, children ) { //The propName variable is used to store the element properties that will be used later let propName; //the props variable is used to store the key-value pair collection of element properties const props = {}; //key, ref, self, and source are all attributes of React elements, so there is no need to go into it here let key = null ; let ref = null ; let self = null ; let source = null ; //What is stored in the config object is the attribute of the element if (config != null ) { //The first thing to do after coming in is to assign values to the ref, key, self and source attributes in turn if (hasValidRef(config)) { ref = config.ref; } // Stringize the key value here if (hasValidKey(config)) { key = '' + config.key; } self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; //Next is to move all the properties in config to props, the previously declared object for (propName in config) { if ( //Filter out the properties that can be added to the props object hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName) ) { props[propName] = config[propName]; } } } //childrenLength refers to the number of child elements of the current element, the subtracted 2 is the length occupied by the two parameters type and config const childrenLength = arguments .length- 2 ; //if you leave out type and config, there is only The next parameter generally means that if the text node appears (childrenLength === 1 ) { //directly assign the value of this parameter to props.children props.children = children; //handle the case of nesting multiple child elements ) else if (childrenLength> 1 ) { //declare an array of child elements const childArray = Array (childrenLength); //push child elements into the array for ( let i = 0 ; i <childrenLength; i++) { childArray[i] = arguments [i + 2 ]; } //Finally assign this array to props.children props.children = childArray; } //Process defaultProps if (type && type.defaultProps) { const defaultProps = type.defaultProps; for (propName in defaultProps) { if (props[propName] === undefined ) { props[propName] = defaultProps[propName]; } } } //Finally, return a call to the ReactElement execution method, and pass in the parameters just processed return ReactElement( type, key, ref, self, source, ReactCurrentOwner.current, props, ); } Copy code

Without looking at the parameters, we will first look at the name of the return value and the name of the function. Our initial guess,

jsx
Is through
createElement
This function to create a
React
Elements, and then by
ReactDOM.render
To render to the element with the specified name.

ok, then the jsx element we usually write is

ReactElement
Something generated. Let's see
ReactElement
What is generated.

We first write what we usually write

jsx
Give it a print.

Intuitively, does it feel like this is a

Virtual DOM
Node, he has type and then
div
, Will the corresponding
html
of
div
label? and also
className
, This obviously corresponds to
class
. Let's take a look.

ReactElement

const ReactElement = function ( type, key, ref, self, source, owner, props ) { const element = { //This is the identifier of a React node $$typeof : REACT_ELEMENT_TYPE, //Obviously the corresponding html tag type : type, key : key, ref : ref, props : props, //Who created the record, I don t know what it is for the time being. Dig a hole first _owner : owner, }; //The configuration in the development environment is mainly Object.freeze, which can be checked on MDN. I will not introduce more if (__DEV__) { //The validation flag is currently mutative. We put it on //an external backing store so that we can freeze the whole object. //This can be replaced with a WeakMap once they are implemented in //commonly used development environments. element._store = {}; //To make comparing ReactElements easier for testing purposes, we make //the validation flag non-enumerable (where possible, which should //include every environment we run tests in), so the test framework //ignores it. Object .defineProperty (element._store, 'validated' , { configurable : false , enumerable : false , writable : true , value : false , }); //self and source are DEV only properties. Object .defineProperty(element, ' _ self' , { configurable : false , enumerable : false , writable : false , value : self, }); //Two elements created in two different places should be considered //equal for testing purposes and therefore we hide it from enumeration. Object .defineProperty(element, ' _source ' , { configurable : false , enumerable : false , writable : false , value : source, }); if ( Object .freeze) { Object .freeze(element.props); Object .freeze(element); } } return element; }; Copy code

After reading it, is it the same as the node we saw? First of all, mark it

$$typeof
for
react node
. Then it is the normal parameter transfer, such as
key
,
ref
,
props
and many more.

ReactDOM.render

This is the operation of the React node rendering as a real node. Not much to say, go to the source code!

export function isValidContainer ( node: mixed ): boolean { return !!( node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || (node.nodeType === COMMENT_NODE && (node: any).nodeValue === 'react-mount-point-unstable' )) ); } export function render ( element: React$Element<any>, container: Container, callback:? Function , ) { //Used to throw an error, is to judge whether the container can be found invariant( isValidContainer(container), 'Target container is not a DOM element.' , ); if (__DEV__) { const isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined ; if (isModernRoot) { console .error( 'You are calling ReactDOM.render() on a container that was previously ' + 'passed to ReactDOM.createRoot(). This is not supported.' + 'Did you mean to call root.render(element)?' , ); } } //This involves some of the fiber architecture, I want to talk about it later, and dig a hole return legacyRenderSubtreeIntoContainer( null , element, container, false , callback, ); } Copy code

Does it feel simple, remove

__DEV__
Circumstance. It also returns the result of a function. . .

ReactDOM.hydrate

I found this function very interesting. It is different from ReactDOM.render with only one line of code.

legacyRenderSubtreeIntoContainer( null, element, container, -false, + true, callback, ); Copy code

First of all, this

hydrate
Means water injection. The rough meaning is to add moisture and color to a node. Before it was for
SSR
In the process of adding click events and so on. in
React17
Will be eliminated later
ReactDOM.Render
, All use
ReactDOM.hydrate
Instead.

A sentence from React's official website

use

ReactDOM.render()
The hydrate operation on the server-side rendering container has been deprecated and will be removed in React 17. As an alternative, use
hydrate()
.

Why use JSX

Here is a little trick to solve the problem. Why XX is actually asking you, the benefits of XX. ok, then it's easy to answer next

First of all, because if you don t

jsx
, We have to write hundreds in the code
React.crearteElement
.

2. this syntactic sugar allows developers to use familiar

HTML
Label to create
Virtual DOM
, Reduce the cost of learning. Improve development efficiency and development experience

Remaining pit

  • legacyRenderSubtreeIntoContainer (involving fiber architecture
  • _owner (when created, what is the use of this attribute

If you like it, please give me a thumbs up! ! If you have any questions, you can point it out in the comment section

index

zh-hans.reactjs.org/docs

www.babeljs.cn/docs/