React—03—描述交互
vue的重新渲染:
是通过修改data、computed、watch等添加到响应式系统的变量,然后vue会自动重新渲染;
react的重新渲染:
通过setXXX的hook进行重新渲染,因为设置状态会请求一个新的重新渲染。
不清楚排队机制所造成的bug:
react的重新渲染也是要排队进行的,不是设置状态后立马进行重新渲染。这个其实和vue的nexttick一样,都是这个tick内所有的更改都是在nexttick的时候才会统一重新渲染。
而react的setXXX这个设置状态的hook一定要在重新渲染后才能生效,所以出现了这个bug。vue没这个setXXX的hook所以所有状态的改变都是立即生效的,只是重新渲染也要在nexttick。
我调用了三次increment()函数,但是在调用第一次increment()函数时,score = 0+1, 并没有发生重新渲染,所以setScore没有生效,store的值在这个tick内还是0,
那么第二次调用的时候,store的值还是0,score = 0+1,
那么第三次调用的时候,store的值还是0,score = 0+1,
那么最后于重新渲染的时候,执行了三遍的score = 0+1, 那么score还是1.
一、响应事件
1.1如何添加事件
第二种会在渲染的时候就立即执行。
注意,第一种是值传递了函数的地址,第二种是在渲染的时候就会立即执行这个函数;
onClick事件,如果是button或者div元素这种原生的html元素,那么是会被浏览器监听的。
如果是我们自定义的组件上加了一个onClick事件,那么就是一个自定义事件罢了,我们真的鼠标点击了这个组件,没有任何影响。
1.2组件的记忆useState
点击next按钮,index并不会加1,
两个原因:
原因一:index是局部变量,这种定义方式并没有让index加入到react的响应式系统中,然后执行index=index+1后,页面不会重新渲染。
原因二:就算过了一段时间因为这种那种原因组件重新渲染了,又因为index在Gallery组件中定义,还算是局部变量,每次Gallery重新渲染的时候,都会重新执行一遍let index = 0;
useState
第一很好地解决了上述的两个问题,通过setState去修改state可以触发重新渲染,state在自己的响应式系统里;
第二useState是隔离且私有的,不同的实例会有不同的state;(果你希望两个组件保持其 states 同步怎么办?在 React 中执行此操作的正确方法是从子组件中删除 state 并将其添加到离它们最近的共享父组件中)
state是一个快照,把一些列state更新加入队列
设置 state 不会更改现有渲染中的变量,但会请求一次新的渲染。
和vue的necttick一样,设置state也不是立马就执行,也是在下一个tick中统一执行这部分代码,当然执行顺序就是加入tick的先后顺序。
他这里有个例子很有趣,除了默认的更新state传入要给同类型的值setState(newData)外,还可以传入一个更新函数,更新函数参数是老的值setState(n => n + newData)
类比到vue里,其实就在nexttick中,this.data = 1;this.data = 1;this.data = 1;执行了三遍;
相当于this.data = this.data + 1;this.data = this.data + 1;this.data = this.data + 1;代码执行了3遍。
等到把这些函数都处理好后,渲染阶段也进入了尾声,react开始进行真实dom的重新渲染;即在nexttick中先处理逻辑,最后重渲染dom;
事件处理函数执行完成后,React 将触发重新渲染阶段。在重新渲染阶段,React 将先会处理队列,队列中的更新函数会在渲染期间执行,因此 更新函数必须是 纯函数 并且只 返回 结果。
更新state的对象
使用setPersion修改一个嵌套对象时会很麻烦,因为我们要给一个完整的对象属性做替换,
这个时候,如果要修改嵌套对象,使用useImmer就会很方便,直接修改那个属性就可以了,user Immer内部会帮助我们内部做替换。
为什么要用useState?上面已经给了答案,那么
为什么不能直接修改state?而要用useState的setXXX?
除了下面的原因,我觉得还有就是我们如果直接修改state,不会进行响应式更新,但如果使用setXXX就会响应式更新;(官方文档说的:因为并没有使用 state 的设置函数,React 并不知道对象已更改。所以 React 没有做出任何响应)
更新state的数组
数组也是一种特殊类型的对象,所以我们修改数组的时候也不能直接修改数组元素本身。
当然了,如果使用immer语法是可以的。