In this post, we will focus on JSX, starting with the following three questions
- what
JSX
? He andjs
What does it matter? JSX
What are the underlying principles?- why
React
Want to chooseJSX
?
What is JSX?
It’s called JSX, and it’s a syntax extension for JavaScript. JSX gives JavaScript more visual power as a data structure that describes component content.
What is the underlying principle of JSX?
We tried it on the Babel website, typing our JSX content on the left and compiling it to the right:
As you can see from the figure, JSX is compiled by Babel as a react.createElement method. JSX does not need the React module to be used in the React component. After React17.0, we can use JSX without the React module. Details can be found on the website: Introducing the new JSX transformation.
createElement
JSX implements the react. createElement method
* Create and return a new ReactElement of the given type. * See https://reactjs.org/docs/react-api.html#createelement */ /** ** @param {*} type type: HTML tag type (div), component (function component, class component), tell us what type of component it is * @param {*} config: Props, classname, etc. * @props {*} children: Child nodes (text content, Return () {return () {return () {return () {return () {return (); // Props props = {}; // props props = {}; // React let key = null; let ref = null; let self = null; let source = null; // config ==> props className style etc. If (config! If (hasValidRef(config)) {ref = config.ref; if (__DEV__) { warnIfStringRefCannotBeAutoConverted(config); } } if (hasValidKey(config)) { if (__DEV__) { checkKeyStringCoercion(config.key); } key = '' + config.key; } self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; // Add all the other properties to the props object we declared. for (propName in config) { if ( hasOwnProperty.call(config, propName) && ! RESERVED_PROPS.hasOwnProperty(propName) ) { props[propName] = config[propName]; Const childrenLength = arguments.length - 2; const childrenLength = childrenLength - 2; If (childrenLength === 1) {props. Children = children; } else if (childrenLength > 1) {// Save the childrenLength to an array, Const childArray = Array(childrenLength); const childArray = Array(childrenLength); for (let i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } // The childArray array is not allowed to be modified in the development environment See [Object. Freeze] the if (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) (__DEV__) { if (Object.freeze) { Object.freeze(childArray); }} // Assign the children node (array) we got to props. Children property props. Children = childArray; } // Handle defaultProps (the default value set). When handling components, have their own default defaultProps, /** const FunctionComponent = (props) => <div className='function-title'>FunctionComponent, {props.name} </div> * FunctionComponent.defaultProps = { name: 'xiong' } */ if (type && type.defaultProps) { const defaultProps = type.defaultProps; For (propName in defaultProps) {// props is the same as defaultProps; If (props[propName] === undefined) {props[propName] = defaultProps[propName]; if (props[propName] === undefined) {props[propName] = defaultProps[propName]; }}} // omit... // ReactElement merges our parameters and adds the React node identifier $$typeof: REACT_ELEMENT_TYPE; _owner attribute / / return a ReactElement element such as the return ReactElement (type, key, ref, the self, the source, ReactCurrentOwner. Current, props, ); }Copy the code
ReactElement
Const ReactElement = function(type, key, ref, self, source, owner, props) {const ReactElement = function(type, key, ref, self, source, owner, props) { const element = { // This tag allows us to uniquely identify this as a React Element $$typeof: // built-in properties that belong on the element type: type, // Corresponding HTML tag key: key, ref: ref, props: props, // Record the component responsible for creating this element. _owner: owner, }; / /... Freeze // Returns the element we generated that contains component data. Element return Element; };Copy the code
After we write JSX, can we guess what React does for us? What JSX is converted to?
JSX
It’s going to be resolved intoReact.createElement
Method that takes multiple arguments, the first representing the type (tag name, component name), the second representing the props, classname, and so on passed in, and the third and subsequent child nodesReact.createElement
What does the method do? First of all,Ref, key, self and source
Property, and then fromconfig
Add other attributes to theprops
, and then parses its child nodes (which may have multiple nodes) asprops.children
And will beprops
And the component ofdefaultProps
Merge, and finally callReactElement
Function to pass in our combined dataReactElement
The React function merges our arguments, focusing on adding identifiers to the React node
$$typeof: REACT_ELEMENT_TYPE returns a combined object
const jsx = <div className='jsx-title'>jsx</div> // ===> { $$typeof: Symbol(react.element) key: null props: {className: 'jsx-title', children: 'JSX '} ref: null type: "div" (() => {}) _owner: null _store: {validated: true} _self: undefined _source: {fileName: '/Users/xiongling/Desktop/react-analysis/react-demo/src/App.js' }Copy the code
At this point, our JSX will be parsed into a React Element object.
Why React chose JSX?
More specifically, why do we use JSX? First of all, if we didn’t apply JSX, we would have to write hundreds of react. crearteElements in our code, which are nested in various loops and not very readable. So when we use JSX syntax sugar, we can let developers use familiar HTML tags to create virtual DOM, reduce learning costs, improve development efficiency and experience.
Other intellectual
How to determine if the object returned by React. CreateElement is a React Element?
React provides a global API called React. IsValidElement, which is a non-null object and has the React node identifier $$typeof: REACT_ELEMENT_TYPE, so it is a valid React Element.
export function isValidElement(object) { return ( typeof object === 'object' && object ! == null && object.$$typeof === REACT_ELEMENT_TYPE ); }Copy the code
How to distinguish components from function components?
Both class components and function components become React Element objects, which have a type attribute that identifies their type. The class component is the name of its class, and the function component is the function name or anonymous function
AppClass instanceof Function === true;
AppFunc instanceof Function === true;
Copy the code
You can’t distinguish ClassComponent from FunctionComponent by reference type. So how does React differentiate? React uses the isReactComponent variable on the ClassComponent prototype to determine if it is a ClassComponent.
ClassComponent.prototype.isReactComponent = {};
Copy the code
Are JSX nodes the same as Fiber nodes?
JSX is a data structure that describes the content of the current component. It does not contain the relevant information required for schedule, Reconcile and Render components.
For example, the following information is not included in JSX:
- The component is being updated
priority
- The component’s
state
- The component is typed forRendererthe
tag
Reference article:
- React Technology revealed
- React what is JSX