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地址,那么本章我们将用我们的开发板作为客户端去连接服务器,并做数据回环测试:收到服务器发送的数据,并回传给服务…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
