May 31, 2021 Article blog
1. Why react should be introduced
2. Why use className instead of class
3. Why do properties use small humps
4. Why call super and pass props in constructor
5. Why does the component start with capital?
6. Why call the method bind this
Online comments that React is harder to get on than Vue may be difficult to understand deeply about JSX, or that some of the characteristics of ES6 are not deeply understood, leading to some incomprehensible points, and then say that React is harder to get hands on and anti-human, so I'm going to write two articles about novice React learning when it's easy to write confusing points.
When writing React, you might write code like this:
import React from 'react'
function A() {
// ...other code
return <h1>前端桃园</h1>
}
You must have wondered why React was introduced when none of the following code was used.
If you delete
import React from ‘react’
you will also report the following error:
So where on earth did this React get us to introduce React and report it wrong, and for that reason, then JSX didn't make it too clear.
You can say the code above (ignore the import statement) and put it in the online babel for a conversion, and find that babel will convert the above code into:
function A() {
// ...other code
return React.createElement("h1", null, "前端桃园");
}
Because essentially, JSX is just for
React.createElement(component, props, ...children)
the syntax sugar provided by the function.
class
on an element requires using
className
API:
const element = document.createElement("div")
element.className = "hello"
const element = {
attributes: {
class: "hello"
}
}
class
variable will go wrong:
const { class } = { class: 'foo' } // Uncaught SyntaxError: Unexpected token }
const { className } = { className: 'foo' }
const { class: className } = { class: 'foo' }
Other discussions can be seen: interesting topics, why jsx uses classNameclass instead of class
Because JSX syntax is closer to JavaScript than HTML, React DOM uses
camelCase
(Little Hump Naming) to define the name of the property instead of the naming convention for the HTML property name.
Introduction from JSX
This is a piece of code on the official website, see: State and Lifecycle
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
And there's a passage that not only lets us call
super
but also passes
props
in, but doesn't tell us why we're doing it.
I don't know if you've ever wondered why you call
super
and pass
props
so let's solve the puzzle.
Why call super
In fact, this is not the limit of React, this is the limitation of JavaScript, in the constructor if you want to call this, then call super in advance, in React, we often initialize state in the constructor,
this.state = xxx
so we need to call super.
Why pass props
You might think that
super
must be passed in
props
otherwise
React.Component
will not be able to initialize
this.props
class Component {
constructor(props) {
this.props = props;
// ...
}
}
However, if you accidentally miss
props
and call
super()
directly, you can still access
this.props
in
render
and other methods (try it if you don't believe it).
Why is this okay? Because React assigns props to the instance object you just created after the constructor is called:
const instance = new YourComponent(props);
instance.props = props;
props
can be used without transmission for a reason.
But does that mean you can replace
super(props)
with super
super()
you use React?
That's not going to work, or the official website won't recommend calling props, although React assigns a value to
this.props
after the constructor runs, but
this.props
is still unusable until it ends with the constructor after the
super()
call.
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// Inside your code
class Button extends React.Component {
constructor(props) {
super(); // 忘了传入 props
console.log(props); // {}
console.log(this.props); // undefined
}
// ...
}
If a method to access
props
is called in the constructor, the bug is more difficult to locate.
So I strongly recommend always using supers, even if it's not required:
class Button extends React.Component {
constructor(props) {
super(props); // We passed props
console.log(props); // {}
console.log(this.props); // {}
}
// ...
}
The code above ensures that
this.props
always have values.
If you want to avoid the above problems, you can simplify the code with the class property proposal:
class Clock extends React.Component {
state = {date: new Date()};
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
More details can be found on Dan's blog
As mentioned earlier, JSX is
React.createElement(component, props, …children)
provides the type of syntax sugar, the type of component is:
string/ReactClass type
let's look at exactly when the string type will be used and under what circumstances the ReactClass type type will be used
For example (string): In jsx we write one
<div></div>
When you convert to js, it becomes
React.createElement("div", null)
For example (ReactClass type): In jsx we write one
function MyDiv() {
return (<div><div>)
}
When you convert to js, it becomes
function MyDiv() {
return React.createElement("div", null);
}
React.createElement(MyDiv, null);
In the example above, if you lowercase the initials in MyDiv, the following
function myDiv() {
return (<div><div>)
}
When you convert to js, it becomes
function MyDiv() {
return React.createElement("div", null);
}
React.createElement("myDiv", null);
Since the dom of myDiv cannot be found, an error is reported.
Prerequisite knowledge: A deep understanding of this in JavaScript
I believe that when you first write React, many friends might write code like this:
class Foo extends React.Component {
handleClick () {
this.setState({ xxx: aaa })
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
)
}
}
Discover that
this
will be reported as
undefined
error, and then may be confused about the handling of the event, and then go to the official website of the event processing has the following paragraph:
You must be careful with
this
in the JSX callback function, where class's method does not bindthis
default in JavaScript. If you forget to bindthis.handleClick
and pass it intoonClick
when you call thisthis
value of this isundefined
This is not React-specific behavior; In general, if you don't add
()
after a method, such asonClick={this.handleClick}
you should bind this tothis
method.
Then after you look at the examples and suggestions on the official website, you know that you need to bind this to
this
event handler to solve it, and think of this:
class Foo extends React.Component {
handleClick () {
this.setState({ xxx: aaa })
}
render() {
return (
<button onClick={this.handleClick.bind(this)}>
Click me
</button>
)
}
}
But maybe you haven't thought about why bind this is needed. If you don't understand, the js foundation isn't playing well.
How does React handle events?
Let's first look at how React handles events.
React's events are synthetic events, the internal principles are very complex, and I'll just cover the key, principles that can be used to answer this question here (you should write a post-react event principle later, so stay tuned).
As mentioned in the previous article, jsx is actually
React.createElement(component, props, …children)
the syntax sugar provided by the function, then this jsx code:
<button onClick={this.handleClick}>
Click me
</button>
will be converted to:
React.createElement("button", {
onClick: this.handleClick
}, "Click me")
Learn about the above, and then simply understand how react
update
handles events, react registers events to
document
uniformly through
addEventListener
when components load
mount
update, and then there is an event pool that stores all events and distributes them through
dispatchEvent
when they are triggered.
So you can simply understand that
this.handleClick
will be called as a callback function.
Understand this, and then see why the callback function
this
This is a brief review
Inside a function, the value of
this
depends on how the function is called.
If you can't understand the above sentence, then you may need to stop to read the article and check the relevant information, otherwise you may not understand the following, if you are lazy, look at the MDN prepared for you.
By introducing event handling above, we simulate that in the render function of a class component, it's a bit like doing something like this:
class Foo {
sayThis () {
console.log(this); // 这里的 `this` 指向谁?
}
exec (cb) {
cb();
}
render () {
this.exec(this.sayThis);
}
}
var foo = new Foo();
foo.render(); // 输出结果是什么?
You'll find that the end result output is
undefined
and if you don't understand why the output is
undefined
then as mentioned above, you need to understand the principle of this deeply.
If you can understand that the output is
undefined
then I think you can understand why bind this is needed.
So you might ask: Why didn't React automatically integrate bind into the render method? Bind in when exec calls back, like this:
class Foo {
sayThis () {
console.log(this); // 这里的 `this` 指向谁?
}
exec (cb) {
cb().bind(this);
}
render () {
this.exec(this.sayThis);
}
}
var foo = new Foo();
foo.render(); // 输出结果是什么?
Because bind is affected by multiple render calls each time, it is officially recommended that you manually bind in the constructor to achieve performance optimization.
There are several ways to write about event handling, so let's compare them:
1. Direct bind this type
Just as the article begins, bind this is directly at the event
class Foo extends React.Component {
handleClick () {
this.setState({ xxx: aaa })
}
render() {
return (
<button onClick={this.handleClick.bind(this)}>
Click me
</button>
)
}
}
Pros: Write it easily and you can finish it in one breath without moving the cursor to other places.
Cons: Performance is not very good, this way is the same as the react internal help you bind, each time the render will bind, and if there are two elements of the event handler is the same, but also to bind, this will write more code, and bind twice, performance is not too good. (In fact, this performance is often not a performance bottleneck place, if you feel easy, so write completely no problem)
2. constuctor manual bind type
class Foo extends React.Component {
constuctor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick () {
this.setState({ xxx: aaa })
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
)
}
}
Pros: Better performance than the first, because the constructor executes only once, it only binds once, and if there are multiple elements that need to call the function, there is no need to repeat bind, basically addressing the two disadvantages of the first.
Disadvantages: There are no obvious shortcomings, the hard words are too ugly, and then not easy (I feel ugly, you feel not ugly just write it).
3. Arrow function type
class Foo extends React.Component {
handleClick () {
this.setState({ xxx: aaa })
}
render() {
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
)
}
}
Pros: Easy to do, good-looking.
Cons: Each time the render creates a function repeatedly, performance is poor.
4. public class fields type
This
class fields
is still in the experimental stage, and as far as I know, it has not yet been included in the standard, as can be seen here.
class Foo extends React.Component {
handleClick = () => {
this.setState({ xxx: aaa })
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
)
}
}
Pros: Good-looking, good performance.
Cons: There are no obvious drawbacks, and if hard to say it might be to install an extra babel plug-in to support this syntax.
I usually use these four writing methods, my side from the beauty of the code, performance and whether it is convenient to make a simple comparison of the various writing. In fact, each method in the project is no problem, performance can basically be ignored, for aesthetics and handy more subjective, so overall is to see everyone's preferences, if hard to recommend, I still recommend the fourth type of writing, beautiful and do not affect performance.
This question is a question that our company's back end asked when writing React, why can't we just modify state, setState. I was thinking that moving from vue to React might also be a question, because vue modification states are changed directly.
If we understand how setState works, we might be able to answer that question, and what setState does is not just modify the value of
this.state
but most importantly, it triggers React's update mechanism, diff, and then updates the patch section to the real dom.
If you go directly
this.state.xx == oo
the value of state does change, but if it doesn't trigger an update to the UI, it's not data-driven.
So why does Vue directly modify data to trigger an update to the UI? B ecause Vue collects these datas when it creates the UI, and the visitor properties of these datas are rewritten, the UI update is triggered in this overriding method. If you want to know more about the principles of vue, you can buy an analysis of Vue .js internal operation mechanism.
If you don't understand the properties of the visitor, read this article: Get a deeper understanding of the objects in JS
1. Is setState synchronous or asynchronous?
My answer is to perform the process code synchronization, but the order in which synthetic events and hook functions are called before the update results in the synthesis events and hook functions not being able to immediately get the updated values, in the form of the so-called "asynchronous", so it manifests itself sometimes synchronously and sometimes "asynchronous".
2. When is synchronization and when is asynchronous?
"Asynchronous" only in synthetic events and hook functions, and synchronized in native events and native APIs such as setTimeout/setInterval. Simply understood as being "asynchronous" in a function controlled by React, the opposite is the case with synchronization.
3. So why is there an asynchronous situation?
In order to do performance optimization, delaying updates to state until the last batch merge to render is a great benefit to the performance optimization of your app, and if you re-render the real dom every time the state changes, it will be a huge performance drain.
4. How can the updated state be accurately obtained in a function that exhibits asynchronousness?
Get the updated results with callback in the second
setState(partialState, callback)
Or you can show synchronization by passing a function to setState:
this.setState((state) => {
return { val: newVal }
})
5. What about the principle of asynchronousness?
Direct source code is certainly not enough space, you can read this article: Do you really understand setState?
I'll let you understand here in the simplest language: in React's setState function implementation, you'll be judged by the isBatchingUpdates variable whether to update this.state directly or later in the queue. Then there is a batchupdate function that can modify isBatchingUpdates to true, and the batchedUpdate function is called before React calls the event handler, or before the lifecycle function, so that the setState does not update this.state synchronously, but instead puts it in the update queue for subsequent updates.
This way you can understand why native events and setTimeout/setinterval calls this.state are updated synchronously, because react called by these functions can't call the batchupdate function to set isBatchingUpdates to true, so this time setState defaults to false, and then updates are synchronized.
At last
SetState is a very important method for React, and it's worth studying his principles.
These are
W3Cschool编程狮
about
novice learning react confused points (can also be reviewed, recommended collection!)
I
hope it will be helpful to you.