一. 渲染两次问题
注意:
在严格模式
下,React 开发环境会可以执行两次渲染,用于突出存在的问题!!结果就会导致组件中的代码在渲染时好像被执行了两次!!
解决方法:
关闭严格模式即可!!
二. 重新渲染时各部分代码执行问题
以函数组件为例:
可以把一个组件中的代码分为以上几个部分!!
函数组件外部
的代码,只在组件初次渲染时执行一次!- 函数组件的每次重新渲染,都是重新执行这个组件声明函数!!!,所以说
函数组件内部
的代码,在每次重新渲染时都会执行!! 生命周期中
(Effect Hook中的代码会根据,该 hook 的第二个参数的不同,而执行的时机不同,且看下述分析)事件函数
,当然是在事件被触发时才会执行!!!return 中
的也是,每次重新渲染都会执行!!!
三. Effect Hook 模仿各个生命周期以及参数问题
useEffect()
该 hook 接收一个包含命令式、且可能有副作用代码的函数。
在函数组件体内(这里指在 React 渲染阶段)改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性。
所以可以使用 useEffect() 完成副操作!!
执行时机:
-
默认情况下,effect 会在每轮渲染结束后执行,但可以选择让它只在在某些值改变时执行!!
-
与
componentDidMount
、componentDidUpdate
不同的是,在浏览器完成布局与绘制之后,传给useEffect
的函数会延迟调用。这使得它适用于许多常见的副作用场景,比如设置订阅和事件处理等情况!!
条件执行:
如果不给 effect 传第二个参数,它就会默认在每次函数更新后都执行,如果此时在 effect 里面执行的是 发起请求 操作,那么就会造成很大的性能问题,因为每次因为函数组件中的某个状态更新而导致的组件重新渲染,都会再次执行该 effect ,从而再次发起请求!!!
所以可以给 useEffect
传递第二个参数,它是 effect 所依赖的值数组。即只有该数组中的某项值发生更新后,才会再次执行该 effect !!!
模拟各个生命周期:
componentDidMount:
useEffect( ( )=>{
console.log("只有首次渲染才执行")
} , [ ] )
// 第二个参数是一个空数组,表示只有第一次渲染时才会执行,以后都不会执行!!!
componentDidUpdate
useEffect( ( )=>{
console.log("监听的状态改变后才执行")
} , [ n ] )
// 第二个参数传入,该 effect 要监听的状态!
componentWillUnmount
useEffect( ( )=>{
return ()=>{ console.log("在组件销毁时执行") }
} , [ n ] )
依赖性(第二个参数)需注意的问题:
一定要确保数组中包含了所有外部作用域中会发生变化且在 effect 中使用的变量,否则你的代码会引用到先前渲染中的旧变量。
因为该 effect 中使用了外部的变量,但该 effect 只在首次渲染时执行一次,所以第一次执行会把外部的 count 的值,保存在闭包中,之后计时器使用的都是内部的闭包里面存的 count 的值,0 。所以展现的会一直是 1 !!