react入门知识点
1.useEffect
const [count, setCount] = useState(0)
useEffect(() => {
console.log("useEffect:", count)
}, [])
(1) useEffect的参数
第一个参数
- 第一个参数是函数(这里叫effect函数),它的作用是,在页面渲染后执行这个函数。所以可以把ajax请求等放在这里执行;
第二个参数(可选)
- 不传参数:组件的初始化和更新都会执行 ,造成数据重复渲染,导致页面卡顿。
- 空数组:初始化调用一次之后不再执行,相当于componentDidMount,effect 不依赖于 props 或 state 中的任何值,所以它永远都不需要重复执行
- 一个值的数组:该值有变化就执行。比如说传[count],React 将对前一次渲染的count和后一次渲染的count进行比较。若相等,React 会跳过这个 effect,实现了性能的优化。
- 多个值的数组:只要有一个值有变化就执行
(2)有时使用useEffect会使组件一直处于不停的刷新,这个是为什么?
报错如下:
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Home (http://localhost:8000/static/umi.js:93407:73)
at Route
at Switch
at Router (http://localhost:8000/static/umi.js:86181:30)
at RouterComponent (http://localhost:8000/static/umi.js:84374:23)
at Provider (http://localhost:8000/static/umi.js:73004:20)
at _DvaContainer (http://localhost:8000/static/umi.js:90776:5)
at http://localhost:8000/static/umi.js:91243:24
at ./src/.umi/plugin-model/Provider.tsx.__webpack_exports__.default (http://localhost:8000/static/umi.js:91706:23)
因为传给useEffect的第二个参数为引用类型(数组或者对象),因为两个引用类型在进行比较的时候永远都是不相等的。
eg:因为在JavaScript中,{} === {}结果是false,{a:1} === {a:1}同样,由此造成了react以为两个值不同,就一直的渲染最终页面死循环。
(3)易错点
-
第二个参数对应的数组中,尽量避免使用引用类型(此时可以在第一个参数也就是执行的副作用函数中调用setState相关的代码)。
-
如果第二个参数中用了引用类型,就应该在第一个参数也就是执行的副作用函数中不要用setState相关的代码,要不然会使得组件陷入到死循环中,报上面的错误。
2.React组件的生命周期(类组件)
(1)挂载阶段
依次执行的钩子函数:
1. constructor() 初始化阶段
2. componentWillMount()
3. render()
4. componentDidMount()
- constructor():ES6中class的构造方法,组件被创建时会首先调用组件的构造方法
作用是初始化state,以及为事件处理程序绑定this
- componentWillMount()——已废用:在组件被挂载在DOM之前调用,而且只会被调用一次
- render()
根据组件的props和state返回一个React元素,用来渲染UI
注意:在render()里面不能调用setState(),因为setState()会触发更新,这意味着组件将再次render,会一直更新和渲染,造成无限循环。
- componentDidMount():在组件被挂载在DOM之后调用,而且只会被调用一次
向服务器端发送网络请求,以及处理依赖DOM节点的操作
可以调用setState()
(2)更新阶段
组件被挂载到DOM之后,props和state都可以引起组件的更新。
- props引起的组件更新,本质上是由渲染该组件的父组件引起的,无论props是否改变,当父组件的render()方法每一次被调用时,都会导致组件的更新。
- State引起的组件更新,则是通过调用this.setState()修改组件的state来触发的。因此,父组件调用render方法或者调用this.setState都会引起组件的更新。
- 依次执行的钩子函数:
1. componentWillReceiveProps()
2. shouldComponentUpdate()
3. componentWillUpdate()
4. render()
5. componentDidUpdate()
- componentWillReceiveProps()
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
只会在由props引起的组件更新过程中被调用,由state引起的组件更新并不会触发该方法的执行