react之Hooks的介绍、useState与useEffect副作用的使用
react之Hooks的介绍、useState与useEffect副作用的使用
- 一、Hooks的基本介绍
- 二、useState的使用
- 2.1 简单使用
- 2.2 数组结构简化
- 2.3 状态的读取和修改
- 2.3 组件的更新过程
- 三、useEffect的使用
- 3.1 副作用介绍
- 3.2 基本使用
- 3.3 依赖
- 3.4 不要对依赖项撒谎
- 3.5 依赖项可以是空数组
- 3.6 清理工作
- 3.7 useEffect的 4 种使用使用方式
- 3.8 发送请求
- 3.9 axios请求本地json数据
一、Hooks的基本介绍
Hooks 是 React v16.8 中的新增功能为函数组件提供状态、生命周期等原本 class 组件中提供的 React 功能可以理解为通过 Hooks 为函数组件钩入 class 组件的特性注意:Hooks 只能在函数组件中使用,自此,函数组件成为 React 的新宠儿可以在项目中同时使用hooks和class
二、useState的使用
2.1 简单使用
一个 Hook 就是一个特殊的函数,让你在函数组件中获取状态等 React 特性useState使用场景:当你想要在函数组件中,使用组件状态时,就要使用 useState Hook 了useState作用:为函数组件提供状态(state)
import { useState } from 'react'const Count = () => { // stateArray 是一个数组const stateArray = useState(0)const state = stateArray[0]const setState = stateArray[1]return (<div>{/* 展示状态值 */}<h1>状态为:{state}</h1>{/* 点击按钮,让状态值 +1 */}<button onClick={() => setState(state + 1)}>+1</button></div>)
}
2.2 数组结构简化
import { useState } from 'react'const Count = () => {// 解构:const [count, setCount] = useState(0)return (<div><h1>计数器:{state}</h1><button onClick={() => setState(state + 1)}>+1</button></div>)
}
2.3 状态的读取和修改
读取状态:useState 提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用
const Counter = () => {const [user, setUser] = useState({ name: 'jack', age: 18 })return (<div><p>姓名:{user.name}</p><p>年龄:{user.age}</p></div>)
}
修改状态:
setCount(newValue) 是一个函数,参数表示:新的状态值调用该函数后,将使用新的状态值替换旧值修改状态后,因为状态发生了改变,所以,该组件会重新渲染
const Counter = () => {const [user, setUser] = useState({ name: 'jack', age: 18 })const onAgeAdd = () => {setUser({...user,age: user.age + 1})}return (<div><p>姓名:{user.name}</p><p>年龄:{user.age}</p><button onClick={onAgeAdd}>年龄+1</button></div>)
}
- 修改状态的时候,一定要使用新的状态替换旧的状态
2.3 组件的更新过程
函数组件使用 useState hook 后的执行过程,以及状态值的变化:
组件第一次渲染:1.从头开始执行该组件中的代码逻辑2.调用 useState(0) 将传入的参数作为状态初始值,即:03.渲染组件,此时,获取到的状态 count 值为: 0
组件第二次渲染:1.点击按钮,调用 setCount(count + 1) 修改状态,因为状态发生改变,所以,该组件会重新渲染2.组件重新渲染时,会再次执行该组件中的代码逻辑3.再次调用 useState(0),此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 14.再次渲染组件,此时,获取到的状态 count 值为:1
- useState 的初始值(参数)只会在组件第一次渲染时生效
核心代码
import { useState } from 'react'const Count = () => {const [count, setCount] = useState(0)return (<div><h1>计数器:{count}</h1><button onClick={() => setCount(count + 1)}>+1</button></div>)
}
三、useEffect的使用
3.1 副作用介绍
内容:
-
使用场景:当你想要在函数组件中,处理副作用(side effect)时,就要使用 useEffect Hook 了
-
作用:处理函数组件中的副作用(side effect)
-
问题:副作用(side effect)是什么?
-
回答:在计算机科学中,如果一个函数或其他操作修改了其局部环境之外的状态变量值,那么它就被称为有副作用
类比,对于 999 感冒灵感冒药来说: -
(主)作用:用于感冒引起的头痛,发热,鼻塞,流涕,咽痛等
-
副作用:可见困倦、嗜睡、口渴、虚弱感
-
理解:副作用是相对于主作用来说的,一个功能(比如,函数)除了主作用,其他的作用就是副作用
-
对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
-
常见的副作用(side effect):数据(Ajax)请求、手动修改 DOM、localStorage、console.log 操作等
总结:
对于react组件来说,除了渲染UI之外的其他操作,都可以称之为副作用
let a = 1const Count = () => {const [count, setCount] = useState(0)const handleClick = () => {setCount(count + 1)}console.log('aaa')axios.post('http://xxx')localStorage.setItem()a = 2return (<div><h1>计数器:{count}</h1><button onClick={handleClick}>+1</button></div>)
}
3.2 基本使用
-
使用场景:当你想要在函数组件中,处理副作用(side effect)时就要使用 useEffect Hook 了
-
作用:处理函数组件中的一些副作用(side effect)
-
注意:在实际开发中,副作用是不可避免的。因此,react 专门提供了 useEffect Hook 来处理函数组件中的副作用
语法:
- 参数:回调函数(称为 effect),就是在该函数中写副作用代码
- 执行时机:该 effect 会在组件第一次渲染以及每次组件更新后执行
- 相当于 componentDidMount + componentDidUpdate
核心代码
import { useEffect } from 'react'const Counter = () => {const [count, setCount] = useState(0)useEffect(() => {document.title = `当前已点击 ${count} 次`})return (<div><h1>计数器:{count}</h1><button onClick={() => setCount(count + 1)}>+1</button></div>)
}
3.3 依赖
内容:
-
问题:如果组件中有另外一个状态,另一个状态更新时,刚刚的 effect 回调也会执行
-
默认情况:只要状态发生更新 useEffect 的 effect 回调就会执行
-
性能优化:跳过不必要的执行,只在 count 变化时,才执行相应的 effect
-
语法:
- 第二个参数:可选,也可以传一个数组,数组中的元素可以成为依赖项(deps)
- 该示例中表示:只有当 count 改变时,才会重新执行该 effect
核心代码
import { useEffect } from 'react'const Counter = () => {const [count, setCount] = useState(0)const [loading, setLoading] = useState(false)useEffect(() => {document.title = `当前已点击 ${count} 次`}, [count])return (<div><h1>计数器:{count}</h1><button onClick={() => setCount(count + 1)}>+1</button><button onClick={() => setLoading(!loading)}>切换 loading</button></div>)
}
3.4 不要对依赖项撒谎
内容:
- useEffect 回调函数(effect)中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中
- 如果 useEffect 回调函数中用到了某个数据,但是,没有出现在依赖项数组中,就会导致一些 Bug 出现!
- 所以,不要对 useEffect 的依赖撒谎
const App = () => {const [count, setCount] = useState(0)// 错误演示:useEffect(() => {document.title = '点击了' + count + '次'}, [])return (<div><h1>计数器:{count}</h1><button onClick={() => setCount(count + 1)}>+1</button></div>)
}
useEffect完全指南:https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/
3.5 依赖项可以是空数组
内容:
-
useEffect 的第二个参数,还可以是一个空数组([]),表示只在组件第一次渲染后执行 effect
-
使用场景:1 事件绑定 2 发送请求获取数据 等
-
语法:
- 该 effect 只会在组件第一次渲染后执行,因此,可以执行像事件绑定等只需要执行一次的操作
- 此时,相当于 class 组件的 componentDidMount 钩子函数的作用
useEffect(() => {const handleResize = () => {}window.addEventListener('resize', handleResize)
}, [])
注意:
- 跟 useState Hook 一样,一个组件中也可以调用 useEffect Hook 多次
- 推荐:一个 useEffect 只处理一个功能,有多个功能时,使用多次 useEffect
3.6 清理工作
内容:
- effect 的返回值是可选的,可省略。也可以返回一个清理函数,用来执行事件解绑等清理操作
- 清理函数的执行时机:
- 清理函数会在组件卸载时以及下一次副作用回调函数调用的时候执行,用于清除上一次的副作用。
- 如果依赖项为空数组,那么会在组件卸载时会执行。相当于组件的
componetWillUnmount
核心代码:
useEffect(() => {const handleResize = () => {}window.addEventListener('resize', handleResize)// 这个返回的函数,会在该组件卸载时来执行// 因此,可以去执行一些清理操作,比如,解绑 window 的事件、清理定时器 等return () => window.removeEventListener('resize', handleResize)
}, [])
3.7 useEffect的 4 种使用使用方式
// 1
// 触发时机:1 第一次渲染会执行 2 每次组件重新渲染都会再次执行
// componentDidMount + ComponentDidUpdate
useEffect(() => {})// 2(使用频率最高)
// 触发时机:只在组件第一次渲染时执行
// componentDidMount
useEffect(() => {}, [])// 3(使用频率最高)
// 触发时机:1 第一次渲染会执行 2 当 count 变化时会再次执行
// componentDidMount + componentDidUpdate(判断 count 有没有改变)
useEffect(() => {}, [count])// 4
useEffect(() => {// 返回值函数的执行时机:组件卸载时// 在返回的函数中,清理工作return () => {// 相当于 componentWillUnmount}
}, [])useEffect(() => {// 返回值函数的执行时机:1 组件卸载时 2 count 变化时// 在返回的函数中,清理工作return () => {}
}, [count])
3.8 发送请求
内容:
-
在组件中,可以使用 useEffect Hook 来发送请求(side effect)获取数据
-
注意:effect 只能是一个同步函数,不能使用 async
- 因为如果 effect 是 async 的,此时返回值是 Promise 对象。这样的话,就无法保证清理函数被立即调用
-
为了使用 async/await 语法,可以在 effect 内部创建 async 函数,并调用
核心代码:
// 错误演示:不要给 effect 添加 async
useEffect(async () => {const res = await axios.get('http://xxx')return () => {}
}, [])// 正确使用
useEffect(() => {const loadData = async () => {const res = await axios.get('http://xxx')}loadData()return () => {}
}, [])
3.9 axios请求本地json数据
需求:发起axios请求本地某json数据第一步:需要将json文件放在 public 目录下 !!!第二步:引入axios import axios from 'axios'第三步:发起请求
import React, { useEffect, useState } from 'react'
import axios from 'axios'
export default function App() {const [list, setList] = useState([])useEffect(() => {
//接口地址可省略 public
axios.get('http://localhost:3000/data.json').then((res) => {console.log('打印res', res.data)setList(res.data.list)})}, [])return (<ul>{list.map((item) => (<li key={item.id}>{item.comment}</li>))}</ul>)
}
相关文章:
react之Hooks的介绍、useState与useEffect副作用的使用
react之Hooks的介绍、useState与useEffect副作用的使用 一、Hooks的基本介绍二、useState的使用2.1 简单使用2.2 数组结构简化2.3 状态的读取和修改2.3 组件的更新过程 三、useEffect的使用3.1 副作用介绍3.2 基本使用3.3 依赖3.4 不要对依赖项撒谎3.5 依赖项可以是空数组3.6 清…...
django——创建 Django 项目和 APP
2.创建 Django 项目和 APP 命令: 创建Django项目 django-admin startproject name 创建子应用 python manager.py startapp name 2.1 创建工程 在使用Flask框架时,项目工程目录的组织与创建是需要我们自己手动创建完成的。 在django中,…...
== 和 equals 的对比 [面试题]
和 equals 的对比[面试题] 文章目录 和 equals 的对比[面试题]1. 和 equals 简介2. Object 类中 equals() 源码3. String 类中 equals() 源码4. Integer 类中 equals() 源码5. 如何重写 equals 方法 1. 和 equals 简介 是一个比较运算符 :既可以判断基本数据类型…...
SpringBoot集成Redis及Redis使用方法
目录 应用背景 Redis简介 更新问题 一:环境配置 1.1: 在pom.xml文件中添加依赖 1.2:配置SpringBoot核心配置文件application.properties 二:在Config文件夹中创建RedisConfig配置文件类 2.1:RedisTemplate中的几个角色&am…...
Redis可以用作数据库吗?它的适用场景是什么?
是的,Redis可以用作数据库。虽然Redis通常被认为是一个内存数据库(in-memory database),但它也可以通过持久化机制将数据保存在磁盘上,以便在重启后恢复数据。 Redis的适用场景包括但不限于以下几个方面: …...
@Param详解
文章目录 背景什么是ParamParam的使用方法使用方法:遇到的问题及因Param解决了什么问题使用与不使用对比 Param是如何进行映射的总结 背景 最近在开发过程中,在写mapper接口是在参数前加了Param注解,但是在运行的时候就会报错,说…...
自定义分页工具类
前言 在日常的开发工作中,会遇到很多不确定的需求场景,无法使用第三方提供的分页组件来实现,那么如何自己实现一个简单的分页工具类呢? 工具类 第一版本: Setter Getter public class PageTool<T> {/*** 当前…...
文本数据保存
文本数据保存 工具目的代码运行结果 工具 pycharm 目的 网址:https://ljgk.envsc.cn/ 需求:获取到地址(address),公司名字(ps_name),创建的时间(create_time)ÿ…...
Python爬虫:抓取表情包的下载链接
Python爬虫:抓取表情包的下载链接 1. 前言2. 具体实现3. 实现代码 1. 前言 最近发现了一个提供表情包的网址,觉得上面的内容不错,于是就考虑用Python爬虫获取上面表情包的下载链接。整体而言,实现这个挺简单的,就是找到提供表情包…...
(文章复现)基于灰狼算法(GWO)的交直流混合微网经济调度matlab代码
参考文献: [1]高瑜,黄森,陈刘鑫等.基于改进灰狼算法的并网交流微电网经济优化调度[J].科学技术与工程, 2020,20(28):11605-11611. [2]邓长征,冯朕,邱立等.基于混沌灰狼算法的交直流混合微网经济调度[J].电测与仪表, 2020, 57(04):99-107. 这两篇文章不管是从模型、…...
【Kubernetes】Kubernetes的调度
K8S调度 一、Kubernetes 调度1. Pod 调度介绍2. Pod 启动创建过程3. Kubernetes 的调度过程3.1 调度需要考虑的问题3.2 具体调度过程 二、影响kubernetes调度的因素1. nodeName2. nodeSelector3. 亲和性3.1 三种亲和性的区别3.2 键值运算关系3.3 节点亲和性3.4 Pod 亲和性3.5 P…...
题目:2511.最多可以摧毁的敌人城堡数量
题目来源: leetcode题目,网址:2511. 最多可以摧毁的敌人城堡数目 - 力扣(LeetCode) 解题思路: 顺序遍历数组,记录上一个我军城堡和没有城堡的位置。当碰到空位置时,若上一次更新的…...
22 | 书籍推荐数据分析
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn import neighbors from sklearn.model_selection import train_test_split from sklearn.preprocessing import...
vscode extension 怎么区分dev prod
开发模式注入环境变量 使用vsode 提供的api...
Java学习手册——第一篇Java简介
今后Java学习手册就来给大家梳理JavaSE的基础知识啦, 除了这个专栏我们还有其他专栏:前端、安全、后端等。 希望大家可以在这里一起讨论学习哟~ Java学习手册——第一篇Java简介 1. Java基础知识2. Java能干嘛3. Java基础环境搭建 1. Java基础知识 出生…...
Prometheus流程图(自绘)-核心组件-流程详解
阿丹手绘流程图:图片可能有点小查看的时候放大看看哈! prometheus核心组件 prometheus server Prometheus Server是Prometheus组件中的核心部分,负责实现对监控数据的获取,存储以及查询。Prometheus Server可以通过静态配置管理…...
回归模型常见评估指标mae,mse,rmse
文章目录 MAE(平均绝对误差)计算公式sklearn实现numpy实现mse(均方误差)计算公式sklearn实现numpy实现rmse(均方根误差)计算公式sklearn实现MAE(平均绝对误差) 计算公式 MAE ( y ,...
服务器数据恢复-断电导致ext4文件系统文件丢失的数据恢复案例
服务器数据恢复环境: 一台服务器挂载一台存储设备,存储中划分一个Lun;服务器操作系统是Linux centos,EXT4文件系统。 服务器故障&分析: 意外断电导致服务器操作系统无法启动,系统在修复后可以正常启动&…...
链表(基础详解、实现、OJ笔试题)
文章目录 🧚什么是链表(链表概念及分类)链表分类单链表和双链表的区别 🚴♂️单链表、双向链表的实现单链表的实现双向链表的实现 🍉链表经典OJ笔试题反转单链表移除链表元素合并两个有序链表链表分割链表的中间结点…...
W5100S-EVB-PICO作为TCP Client 进行数据回环测试(五)
前言 上一章我们用W5100S-EVB-PICO开发板通过DNS解析www.baidu.com(百度域名)成功得到其IP地址,那么本章我们将用我们的开发板作为客户端去连接服务器,并做数据回环测试:收到服务器发送的数据,并回传给服务…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
