Point (b) the novice to learn react confused

Did not see the first chapter of the first friends can go to the venue of the first chapter: point (a) confuse the novice to learn react

The first chapter is also good response, many beginners feel helpful, answer their doubts for a long time since, in fact, fairly basic first article inside, mainly ES6 no deep understanding of grammar and JSX.

The second point which is slightly more difficult, and some need to understand the principles React to thoroughly understand, but do not worry, I have to use the simplest and most straightforward language, even if you are a novice, if they have these questions, you can understand.

Let's start now!

Why call a method to bind this

Prerequisite knowledge:  a deep understanding of JavaScript in this

I believe just wrote React when many of my 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>
 )
 }
}
复制代码

Found will be reported this fault is undefined, and may deal with more doubts about the event, and then go to the official website of the event processing has the following passage:

You must be treated with caution JSX callback function of this, in JavaScript, class methods will not default bindings this. If you forget to bind this.handleClick and it was introduced to onClick, when you call the function of this is undefined. This is not React specific behavior; this is actually the JavaScript function works related. In general, if you are not added after the method (), e.g. onClick = {this.handleClick}, you should be bound to the method of this.

Then after you read the examples and suggestions official website, aware of the need to bind this event handler can be solved, like this:

class Foo extends React.Component {
 handleClick () {
 this.setState({ xxx: aaa })
 }
 render() {
 return (
 <button onClick={this.handleClick.bind(this)}>
 Click me
 </button>
 )
 }
}
复制代码

But you might not have thought about why you need to bind this? If you can not understand it, or js foundation did not play well.

How to React is handling events?

Let's first take a look at how React is handling events.

React event is a synthetic event, the internal principle is very complicated, I am here only the key can be used to answer this question of principle part introduced to (the principle behind the event should write one react so stay tuned).

The articles have said, jsx actually React.createElement (component, props, ... children) function provides syntactic sugar, then this jsx Code:

 <Button this.handleClick the onClick = {}> 
 the Click Me 
 </ Button> 
copy the code

It will be converted to:

React.createElement("button", {
 onClick: this.handleClick
}, "Click me")
复制代码

Understanding of the above, then simply react to understand how to handle events, React when the component is loaded (mount) and update (update), unified registration to the event on the document through addEventListener, then there will be an event pool stores all events , when the event triggered for event distributed by dispatchEvent.

So you can simply understood as the final this.handleClick will call a callback function.

Understand this, then look at why the callback function will be lost this.

this brief review

Inside the function, the value of this depends on how the function is called.

If you do not understand the above sentence, then you may need to stop reading the article, go to check the relevant information, otherwise you may not read the following if you're lazy, then, to see if you're ready for the MDN it.

By the above description of event processing to simulate what the render function class assembly, somewhat similar to do such an operation:

Foo {class 
 sayThis () { 
 console.log (the this); // point where `this` who? 
 } 
 
 Exec (CB) { 
 CB (); 
 } 
 
 the render () { 
 this.exec (this.sayThis); 
 } 
} 
var foo = new new Foo (); 
foo.render (); // output is what? 
Copy the code

You will find that the end result is that the output undefined, if you do not understand why the output is undefined, it is still above said, need to go deep understanding of this principle. If you can understand the output is undefined, then I think you can understand why the need to bind this.

Then you might ask:? ** Why not React to bind automatically integrated into the render method when it ** exec calls the callback bound to go like this:

Foo {class 
 sayThis () { 
 console.log (the this); // point where `this` who? 
 } 
 Exec (CB) { 
 cb.bind (the this) (); 
 } 
 the render () { 
 this.exec (this.sayThis); 
 } 
} 
var foo = new new Foo (); 
foo.render (); // output is what? 
Copy the code

Because multiple calls to render every time bind affect performance, so in the constructor official suggest you manually bind a performance optimization.

Four kinds of event handling contrast

For writing event handling there are several, let's compare to:

1. Direct bind this type

It is like the beginning of the article that directly bind this event there

class Foo extends React.Component {
 handleClick () {
 this.setState({ xxx: aaa })
 }
 render() {
 return (
 <button onClick={this.handleClick.bind(this)}>
 Click me
 </button>
 )
 }
}
复制代码

优点:写起来顺手,一口气就能把这个逻辑写完,不用移动光标到其他地方。

缺点:性能不太好,这种方式跟 react 内部帮你 bind 一样的,每次 render 都会进行 bind,而且如果有两个元素的事件处理函数式同一个,也还是要进行 bind,这样会多写点代码,而且进行两次 bind,性能不是太好。(其实这点性能往往不会是性能瓶颈的地方,如果你觉得顺手,这样写完全没问题)

2. constuctor 手动 bind 型

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>
 )
 }
}
复制代码

优点: 相比于第一种性能更好,因为构造函数只执行一次,那么只会 bind 一次,而且如果有多个元素都需要调用这个函数,也不需要重复 bind,基本上解决了第一种的两个缺点。

缺点: 没有明显缺点,硬要说的话就是太丑了,然后不顺手(我觉得丑,你觉得不丑就这么写就行了)。

3. 箭头函数型

class Foo extends React.Component {
 handleClick () {
 this.setState({ xxx: aaa })
 }
 render() {
 return (
 <button onClick={(e) => this.handleClick(e)}>
 Click me
 </button>
 )
 }
}
复制代码

优点: 顺手,好看。

缺点: 每次 render 都会重复创建函数,性能会差一点。

4. public class fields 型

这种 class fields还处于实验阶段,据我所知目前还没有被纳入标准,具体可见这里。

class Foo extends React.Component {
 handleClick = () => {
 this.setState({ xxx: aaa })
 }
 render() {
 return (
 <button onClick={this.handleClick}>
 Click me
 </button>
 )
 }
}
复制代码

优点: 好看,性能好。

缺点: 没有明显缺点,如果硬要说可能就是要多装一个 babel 插件来支持这种语法。

总结

我平时用的就这四种写法,我这边从代码的美观性、性能以及是否顺手方便对各种写法做了简单的对比。其实每种方法在项目里用都是没什么问题的,性能方面基本上可以忽略,对于美观性和顺手比较主观,所以总体来说就是看大家的偏好咯,如果硬要推荐的话,我还是比较推荐第四种写法,美观而且不影响性能。

为什么要 setState,而不是直接 this.state.xx = oo

这个问题是我们公司后端写 React 的时候提出的问题,为啥不能直接修改 state,要 setState 一下。我在想,从 vue 转到 React 可能也会有这种疑问,因为 vue 修改状态都是直接改的。

如果我们了解 setState 的原理的话,可能就能解答这个问题了,setState 做的事情不仅仅只是修改了 this.state 的值,另外最重要的是它会触发 React 的更新机制,会进行 diff ,然后将 patch 部分更新到真实 dom 里。

如果你直接 this.state.xx == oo 的话,state 的值确实会改,但是改了不会触发 UI 的更新,那就不是数据驱动了。

那为什么 Vue 直接修改 data 可以触发 UI 的更新呢?因为 Vue 在创建 UI 的时候会把这些 data 给收集起来,并且在这些 data 的访问器属性 setter 进行了重写,在这个重写的方法里会去触发 UI 的更新。如果你想更多的了解 vue 的原理,可以去购买染陌大佬的剖析 Vue.js 内部运行机制。

不明白访问器属性的可以看这篇文章:深入理解JS里的对象

setState 是同步还是异步相关问题

1. setState 是同步还是异步?

我的回答是执行过程代码同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,所以表现出来有时是同步,有时是“异步”。

2. 何时是同步,何时是异步呢?

只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout/setInterval等原生 API 中都是同步的。简单的可以理解为被 React 控制的函数里面就会表现出“异步”,反之表现为同步。

3. 那为什么会出现异步的情况呢?

为了做性能优化,将 state 的更新延缓到最后批量合并再去渲染对于应用的性能优化是有极大好处的,如果每次的状态改变都去重新渲染真实 dom,那么它将带来巨大的性能消耗。

4. 那如何在表现出异步的函数里可以准确拿到更新后的 state 呢?

通过第二个参数 setState(partialState, callback) 中的 callback 拿到更新后的结果。

或者可以通过给 setState 传递函数来表现出同步的情况:

this.setState((state) => {
	return { val: newVal }
})
复制代码

5. 那表现出异步的原理是怎么样的呢?

直接讲源码肯定篇幅不够,可以看这篇文章:你真的理解setState吗?。

我这里还是用最简单的语言让你理解:在 React 的 setState 函数实现中,会根据 isBatchingUpdates(默认是 false) 变量判断是否直接更新 this.state 还是放到队列中稍后更新。然后有一个 batchedUpdate 函数,可以修改 isBatchingUpdates 为 true,当 React 调用事件处理函数之前,或者生命周期函数之前就会调用 batchedUpdate 函数,这样的话,setState 就不会同步更新 this.state,而是放到更新队列里面后续更新。

这样你就可以理解为什么原生事件和 setTimeout/setinterval 里面调用 this.state 会同步更新了吧,因为通过这些函数调用的 React 没办法去调用 batchedUpdate 函数将 isBatchingUpdates 设置为 true,那么这个时候 setState 的时候默认就是 false,那么就会同步更新。

最后

setState 是 React 非常重要的一个方法,值得大家好好去研究一下他的原理。

有更多视频资料,加小可乐丫

新手学习 react 迷惑的点(二)


新手学习 react 迷惑的点(二)


Guess you like

Origin blog.51cto.com/14516511/2436767