文章目录
-
- 一,useEffect描述
- 二,它的执行时机
- 三,useEffect分情况使用
-
- [1,不写第二个参数 说明监测所有state,其中一个变化就会触发此函数](#1,不写第二个参数 说明监测所有state,其中一个变化就会触发此函数)
- 2,第二个参数如果是`[]`空数组,说明谁也不监测
- 3,第二个参数如果只传需要监测的state,那只会根据此状态来执行函数
- [4,useEffect 里面return一个回调函数,相当于组件即将卸载的声明周期](#4,useEffect 里面return一个回调函数,相当于组件即将卸载的声明周期)
- 5,注意
一,useEffect描述
我们知道,react 的函数组件里面没有生命周期的,也没有 state,没有 state 可以用
useState
来替代,那么生命周期呢?
useEffect
是 react v16.8
新引入的特性。我们可以把 useEffect hook 看作是componentDidMount、componentDidUpdate、componentWillUnmounrt三个生命周期的组合。可以让你在函数式组件中执行一些副作用操作;
一般副作用操作有:
- 发送ajax请求
- 设置订阅 / 启动定时器
- 手动更改真实DOM
二,它的执行时机
可以看做这三个生命周期函数的组合,也就是在这三个时候会执行
componentDidMount(组件已经挂载)
componentDidUpdate(组件已经更新)
componentWillUnmount(组件即将卸载)
三,useEffect分情况使用
useEffect()
有两个参数:第一个参数是要执行的回调函数,第二个参数是一个依赖项数组数组(根据需求第二个参数可选是否填写),根据数组里的变量是否变化决定是否执行函数;
先看下面简单的案例 ,下面会分情况讨论:
useEffect.js
javascript
import React, { useState, useEffect, useRef } from "react";
// 类型约定
interface interList {
id: number | string; // 类型可能是number也可能是string
text: string;
done: boolean;
}
// 渲染数据
const myList: Array<interList> = [
{ id: 0, text: "参观卡夫卡博物馆", done: true },
{ id: 1, text: "看木偶戏", done: true },
{ id: 2, text: "打卡列侬墙", done: true }
];
const UseEffect: React.FC = (props: any) => {
let [num, setNum] = useState(100);
let [useInfo, SetUserInfo] = useState(myList);
// 0,什么都不传 就是监听所有数据的变化
useEffect(() => {
console.log("我改变了-all");
});
// 1,此处相当于 componentDidUpdate生命周期 组件已经更新完成
useEffect(() => {
console.log("我改变了");
}, [num]); // 只监听num的变化,useInfo的变化不会被监听到
// 2,此处相当于componentDidMount生命周期 组件已经挂载完成
useEffect(() => {
console.log("componentDidMount");
console.log("可以拿到num的值:", num);
}, []);
// 3,此处相当于 componentWillUnmount生命周期 组件即将卸载
useEffect(() => {
// 返回一个回调函数
return () => {
console.log("组件将要卸载了");
};
}, []);
// 其实传不传空数组或不是空数组,useEffect函数里面的回调都会执行一次,也就是说componentWillUnmount这个生命周期页面进来就会执行
// useEffect 这个hoosk也是可以写多个的,尽量不同的处理写在不同useEffect里面
// 点击改变用户信息
const change = () => {
// react 建议不要更改原数组 返回一个数组的拷贝
const newList = [...useInfo, { id: 3, text: "优菈", done: false }];
SetUserInfo(newList);
};
// 点击加一
const add = () => {
setNum(++num);
};
const lis = useInfo.map((item, index) => {
return (
<li key={index}>
{index}:{item.text}
</li>
);
});
return (
<>
<div>
<h3>userEffect 副作用hooks函数</h3>
<br />
<button onClick={add}>点击加一</button>
<p>{num}</p>
<br />
<button onClick={change}>改变用户信息</button>
<ul>{lis}</ul>
</div>
</>
);
};
export default UseEffect;
效果图:
上面代码实现的效果很简单,两个按钮分别改变各自数据的状态,状态的改变会触发 useEffec
t函数的执行,第二个参数的传参影响着此函数的变化,所以下面进行分情况讨论:
1,不写第二个参数 说明监测所有state,其中一个变化就会触发此函数
若不写第二个参数,函数操作每次都会执行 useEffect(method)
监测所有state,相当于 componentDidUpdate
生命周期 - 组件已经更新完成。
javascript
import {useEffect } from "react";
useEffect(() => {
console.log("我改变了-all");
}); // 监听所有数据的变化
2,第二个参数如果是[]
空数组,说明谁也不监测
第二个参数如果是[]
空数组,说明谁也不监测,此时useEffect回调函数
的作用就相当于
componentDidMount
生命周期 - 组件已经挂载完成;
javascript
// 2,此处相当于componentDidMount生命周期 组件已经挂载完成
useEffect(() => {
console.log("componentDidMount");
console.log("可以拿到num的值:", num);
}, []);
3,第二个参数如果只传需要监测的state,那只会根据此状态来执行函数
如果第二个参数中的数组只传了 num
,说明只有 num
改变时,才会触发此useEffect
回调函数,相当于对此数据的监听。
javascript
// 1,此处相当于 componentDidUpdate生命周期 组件已经更新完成
useEffect(() => {
console.log("num改变了");
}, [num]); // 只监听num的变化
当然数组里面也可以写多个([num,userInfo]
),同时监听多个数据的变化。
4,useEffect 里面return一个回调函数,相当于组件即将卸载的声明周期
这句话什么意思呢?
通常,组件是有卸载的生命周期的,使用useEffect 函数
只需在里面return一个回调函数,这个回调函数就相当于 componentWillUnmount
声明周期,可以在里面清除创建的订阅或计时器 ID 等资源。
javascript
// 3,此处相当于 componentWillUnmount生命周期 组件即将卸载
useEffect(() => {
// 返回一个回调函数
return () => {
console.log("组件将要卸载了");
};
}, []);
这里传了空数组说明我不想监听数据的变化,只想在卸载组件的时候执行该逻辑;
5,注意
其实第二个传不传空数组或不是空数组,useEffect函数里面的回调都会执行一次,也就是说页面进来就会自动执行componentWillUnmount
这个生命周期;
useEffect函数
这个hoosk也是可以写多个的,尽量不同的业务处理写在不同useEffect里面;