This article is a bit basic, but it is essential to get a feel for how React internals and implementation work. A primer for further reading, if you already know:
React Component Render => JSX => React.createElement => Virtual Dom
You can skip this article.
A sexy question from a Google engineer
A few months ago, Tyler McGinnis, a front-end developer at Google, sparked discussion about the React component with a tweet from his personal Twitter account.
The question he poses is: what is it about the React component Icon that appears directly in the code above?
The options offered are:
- A. Component Declaration Component Declaration
- B. Component Invocation
- C. Component Instantiation
- D. Using a Component
Interestingly, among the developers who responded:
- 15 percent chose A;
- Eight percent chose B;
- 45% chose C;
- 32% chose choice D;
For front-end engineers experienced in React development, the problem is actually quite understandable. The key is to really understand how React Elements and React Components, and how the JSX abstraction layer connects React. Of course, you also need to understand some superficial inner workings of React.
In this article, we will take a look at the JSX abstraction layer and the React Reconciliation process.
React and React Element what are React elements?
Let’s go back to the beginning and think about the original question, what is React?
In short,
React is a library for building user interfaces.
React is a library that builds a view layer. whatever…) . No matter how complex React itself, no matter how large its ecosystem, building views is always at its core. With this information in mind, we’ll move on to today’s first concept — React Element.
Simply put, the React Element describes what you “want” to see on the screen.
Abstractly, the React Element is an object that describes a Dom Node.
Notice how I use the word “describe,” because React Element isn’t the real thing you see on screen. Rather, it is a collection of descriptions of real things. React Element makes sense. Let’s take a look at the React Element and why it exists:
- JavaScript objects are very lightweight. Use objects as React elements, so React can easily create or destroy those elements without worrying too much about operating costs.
- React has the ability to analyze these objects and, by extension, the virtual Dom. When changes occur, the performance advantage of updating the virtual Dom (over the real Dom) is significant.
To create our object (or React Element) that describes a Dom Node, we can use the React. CreateElement method:
const element = React.createElement(
'div',
{id: 'login-btn'},
'Login'
)Copy the code
Here the react. createElement method takes three arguments:
- A string representing the tag name (div, span, etc.);
- The current React Element needs to have properties;
- The current React Element expresses the content, or a child Element.
The react. createElement method above returns a javascript object:
{
type: 'div',
props: {
children: 'Login',
id: 'login-btn'}}Copy the code
Then when we use the reactdom.render method, which renders onto the real DOM, we get:
<div id='login-btn'>Login</div>Copy the code
And this is the actual Dom node.
So far, there are no hard concepts.
React Element depth and React Component
This article starts with the React Element, not the React Component. I believe you understand the React Element and understand the React Component naturally.
For real development, we didn’t use React. CreateElement directly, because that would be so boring that every component would go crazy. Here comes the React Component, or React Component.
A component is a function or a Class which optionally accepts input and returns a React element.
That’s right, a component is a function or a Class that takes input parameters and returns a React Element instead of writing the boring React Element by hand.
So we actually use the React Component to generate the React Element, which is a huge improvement to the development experience.
Do all React Components need to return a React Element? Return null; Does the React component make sense, and what clever designs and ideas can it implement? (Please pay attention to the author, the next article will be devoted to analysis and explanation.)
Look at the problem from a scenario example
Next, take a look at this code:
function Button ({ onLogin }) {
return React.createElement(
'div',
{id: 'login-btn', onClick: onLogin},
'Login')}Copy the code
We define a Button component that takes the onLogin parameter and returns a React Element. Note that the onLogin parameter is a function and eventually becomes an attribute of the React Element like id:’login-btn’.
Until now, we’ve seen a React Element type with an HTML tag (” span “, “div”, etc). In fact, we can also pass another React Element:
const element = React.createElement(
User,
{name: 'Lucas'},
null
)Copy the code
Notice that the first argument to React. CreateElement is another React Element. This is not the same as when type is an HTML tag. It looks at what Element the class or function returns and sets the right attributes for that Element.
React repeats this process (somewhat recursively) until there is no “createElement call type value class or function”.
Let’s look at the code again:
function Button ({ addFriend }) {
return React.createElement(
"button",
{ onClick: addFriend },
"Add Friend")}function User({ name, addFriend }) {
return React.createElement(
"div",
null,
React.createElement( "p", null, name ),
React.createElement(Button, { addFriend })
)
}Copy the code
There are two components: Button and User. The Dom described by User is a div tag. Inside this div, there is a P tag, which shows the User name. There’s also a Button.
Now let’s look at the react. createElement returns from User and Button:
function Button ({ addFriend }) {
return {
type: 'button',
props: {
onClick: addFriend,
children: 'Add Friend'}}}function User ({ name, addFriend }) {
return {
type: 'div',
props: {
children: [{
type: 'p',
props: { children: name }
},
{
type: Button,
props: { addFriend }
}]
}
}
}Copy the code
As you can see, in the output above, we found four types of type values:
- “button”;
- “div”;
- “p”;
- Button
When React discovers that type is a Button, it queries what React Element the Button component will return and assigns the correct props.
Eventually React will have a complete object representing the Dom tree. In our example, it is:
{
type: 'div',
props: {
children: [{
type: 'p',
props: { children: 'Tyler McGinnis'}}, {type: 'button',
props: {
onClick: addFriend,
children: 'Add Friend'}}}}]Copy the code
React The process of processing this logic is called reconciliation. When does the reconciliation happen?
The answer, of course, is every time setState or reactdom.render is called. This will be explained in more detail in future analysis articles.
All right, let’s get back to that Tyler McGinnis slut.
Do we have everything we need to know to answer this question? Hold on. I’m gonna introduce my old friend JSX.
The role of the JSX
When the React Component was written, everyone was using JSX to describe the virtual Dom. React, on the other hand, could actually exist without JSX.
At the beginning of this article, I mentioned “How does the JSX abstraction layer, which we don’t usually talk about, connect to React?” The answer is simple, because JSX is always called by compiling to React. CreateElement. In general Babel does JSX — > React. CreateElement for us.
Look again at the precedent:
function Button ({ addFriend }) {
return React.createElement(
"button",
{ onClick: addFriend },
"Add Friend")}function User({ name, addFriend }) {
return React.createElement(
"div",
null,
React.createElement( "p", null, name),
React.createElement(Button, { addFriend })
)
}Copy the code
JSX = JSX = JSX
function Button ({ addFriend }) {
return (
<button onClick={addFriend}>Add Friend</button>
)
}
function User ({ name, addFriend }) {
return (
<div>
<p>{name}</p>
<Button addFriend={addFriend}/>
</div>
)
}Copy the code
It’s a compilation output difference.
Final answer and epilogue
So, to answer the question “What does it mean for the Icon component to appear alone?”
After Icon is compiled in JSX, it has:
React.createElement(Icon, null)Copy the code
How do I know these results?
or
Do you want to know how your JSX will compile?
I wrote a small tool to compile JSX in real time and put it in the Github repository. It works like this:
The platform is split into two parts, the left side can write JSX, and the right side can display the compilation result in real time:
And:
The core code of this tool is actually compiled using Babel:
let code = e.target.value;
try {
this.setState({
output: window.Babel.transform(code, {presets: ['es2015'.'react']})
.code,
err: ' '
})
}
catch(err) {
this.setState({err: err.message})
}Copy the code
Interested readers can go to the GitHub repository to see the source code.
conclusion
JSX, React Element, React Component, etc. Some developers may be able to get their hands dirty with projects, but they don’t really understand the concepts, let alone the core ideas of React.
This is pretty basic, but at the same time critical, and will be crucial to understanding the React/Preact source code. On this basis, I will update more in-depth analysis of the React implementation principles for readers who are interested.
My other articles on the React technology stack:
- Learn best practices for writing the React component with examples
- React binds this to javascript
- Uber mobile web version is not enough to create the ultimate performance to see the real chapter
- Analyze the Twitter front-end architecture to learn about complex scenario data design
- React + ES next = ♥
- React+Redux creates “NEWS EARLY”, a one-page app that understands the true nature of the cutting-edge technology stack
- React + Redux project example
- .
Happy Coding!
PS: Author Github warehouse and Zhihu Q&A link welcome all forms of communication.