首先我们要知道在我们的函数体中,在渲染阶段调用我们的会导致渲染的函数,这样会让我们触发递归的调用,就会导致一直的重复渲染一个东西
如何解决这种情况???
让我们的一个事件去触发这个渲染,比如说按钮等等。
为什么按钮就能解决这个问题?
肯定是渲染完了,按钮才会出现吧,这个阶段就处于非渲染阶段
出现新的问题:当新的state值和旧值相同时,它是不会触发组件的重新渲染的?
有可能会
setState()的执行流程(函数组件)
触发函数setCount() 实际上是触发 dispatchSetDate()这个函数
第一步:会先判断,组件当前处于什么阶段
如果是渲染阶段–>不会检查state值是否相同,直接挂在到渲染队列,也就是会发生上面提到的递归渲染
如果不是渲染阶段–>会检查state的值是否相同,如果值不相同,则对组件进行重新渲染-如果值相同,则不对组件进行重新渲染,如果值相同,React在一些情况下会继续执行当前组件的渲染但是这个渲染不会触发其子组件的渲染,这次渲染不会产生实际的这种情况通常发生在值第一次相同时
结论总结:
第一次的值是从0渲染到1,那么我们点击按钮后是会发生渲染的。
第二次点击按钮后我们的值是从1渲染到1,还是会出现渲染,但是这次渲染不会触发子组件的渲染!!!!
如果我们非要在渲染阶段调用怎么办???
我们讨论一下为什么会出现递归调用的原因:因为渲染阶段的函数是立即执行的,那我们让他晚点执行就行,
甚至将我们延迟的值设置为0都可以解决
第一次a和b渲染是启动的时候
第二次a和b渲染是0变到1的过程
第三次就是正常的a出现,但是子组件b没有渲染
但是一般不使用这个方法,而是使用useEffect()
改变函数的执行顺序,useEffect()是一个钩子函数,需要一个函数作为参数,这个作为参数的函数会在组件渲染完毕后执行
所以我们一般将会产生副作用的函数编写到useEffect()函数中,避免影响渲染流程
Effect()的依赖项
默认情况下useEffect()这个函数会在组件渲染完成后调用,并且是在每次渲染结束之后都会执行
在useEffect()可以传递一个第二个参数,
第二个参数是一个数组,在数组中可以指定Effect的依赖项指定后,只有当依赖发生变化时,Effect才会被触发
这里只有ctx触发的时候我们才会触发渲染,减少我们useEffect的执行次数。通常会将我们Effect中使用的所有变量都设置为依赖项,这样一来可以确保这些值发生变化时会触发Effect的执行
但是 像setstate()是由钩子函数useState()生成的,useState()会确保组件的每次渲染都会获取到相同setState()对象,所以钩子函数写不写在依赖项里面都是一样的。
简单来说钩子函数就相当于我们的全局变量,每次都是一样的,而不是像这里的ctx每一次都创建新的值
如果依赖项设置了空数组
如果依赖项设置了一个空数组,则意味Effect只会在组件初始化时触发一次,其余时候怎么都不会执行了
Effect的清理函数
降低数据的过滤次数,提高用户的体验,用户输入完了我们再检索,用户输入完了再检索,类似于防抖
解决方法1:
但是这个方法是有问题的
并不会减少发送请求次数,反而还加了画面的一秒延迟
为什么会产生这个问题????
这几个字母都被挂在了渲染队列里面,一秒后一起执行,并没有减少执行的次数
解决方法
我们应该想,ha开了,我们应该将h关掉,han开启后关掉ha的定时器,所以我们只需要保存最新的定时器!!!!!!
怎么关???
在effect的回调函数中,可以指定一个函数作为返回值,这个函数称为清理函数,他会在下次effect执行前调用,我们可以在这个函数中做一些工作,来清除上一次effect执行所带来的影响
注意执行顺序,当我们的keyword发生变化的时候,return里面的函数先执行的,清除以前的timer。然后再开启新的定时器(timer)