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) 将传入的参数作为状态初始值,即:0
    • 3.渲染组件,此时,获取到的状态 count 值为: 0
  • 组件第二次渲染:
    • 1.点击按钮,调用 setCount(count + 1) 修改状态,因为状态发生改变,所以,该组件会重新渲染
    • 2.组件重新渲染时,会再次执行该组件中的代码逻辑
    • 3.再次调用 useState(0),此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 1
    • 4.再次渲染组件,此时,获取到的状态 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>)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/39650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ZZULIOJ 1193: 单科成绩排序(结构体专题),Java

ZZULIOJ 1193: 单科成绩排序&#xff08;结构体专题&#xff09;&#xff0c;Java 题目描述 有一学生成绩表&#xff0c;包括学号、姓名、3门课程成绩。请按要求排序输出&#xff1a;若输入1&#xff0c;则按第1门课成绩降序输出成绩表&#xff0c;若输入为i&#xff08;1<…

清风数学建模——拟合算法

拟合算法 文章目录 拟合算法概念 确定拟合曲线最小二乘法的几何解释求解最小二乘法matlab求解最小二乘法如何评价拟合的好坏计算拟合优度的代码 概念 在前面的篇幅中提到可以使用插值算法&#xff0c;通过给定的样本点推算出一定的曲线从而推算出一些想要的值。但存在一些问题…

解决内网GitLab 社区版 15.11.13项目拉取失败

问题描述 GitLab 社区版 发布不久&#xff0c;搭建在内网拉取项目报错&#xff0c;可能提示 unable to access https://github.comxxxxxxxxxxx: Failed to connect to xxxxxxxxxxxxxGit clone error - Invalid argument error:14077438:SSL routines:SSL23_GET_S 15.11.13ht…

QT网络编程之TCP

QT网络编程之TCP TCP 编程需要用到俩个类: QTcpServer 和 QTcpSocket。 #------------------------------------------------- # # Project created by QtCreator 2023-08-

mysql截取最后一个字符之前的数据

1、mysql截取最后一个字符之前的数据 select --截取斜杠之前的数据REVERSE(SUBSTR(REVERSE(SPNH-dfg-2012) ; --截取斜杠后的数据 INSTR(REVERSE(SPNH-fg-2012),-)1))2、mysql获取最后一个字符后的数据 select SUBSTRING_INDEX(SPNH-dfg-2012,-,-1) 3、mysql更新某个字段…

SpringBoot 该如何预防 XSS 攻击

XSS 漏洞到底是什么&#xff0c;说实话我讲不太清楚。但是可以通过遇到的现象了解一下。在前端Form表单的输入框中&#xff0c;用户没有正常输入&#xff0c;而是输入了一段代码&#xff1a;</input><img src1 onerroralert1> 这个正常保存没有问题。问题出在了列表…

驱动 实现三个灯的亮灭

1、编写LED灯的驱动&#xff0c;可以控制三个灯&#xff0c;应用程序中编写控制灯的逻辑&#xff0c;要使用自动创建设备节点机制 head.h #ifndef __HEAD_H__ #define __HEAD_H__#define PHY_LED1_MODER 0x50006000 #define PHY_LED1_ODR 0x50006014 #define PHY_LED1_RCC 0x…

设计模式之责任链模式【Java实现】

责任链&#xff08;Chain of Resposibility&#xff09; 模式 概念 责任链&#xff08;chain of Resposibility&#xff09; 模式&#xff1a;为了避免请求发送者与多个请求处理者耦合在一起&#xff0c;于是将所有请求的处理者 通过前一对象记住其下一个对象的引用而连成一条…

什么是ServiceMesh(Istio一)

现在最火的后端架构无疑是微服务了&#xff0c;微服务将之前的单体应用拆分成了许多独立的服务应用&#xff0c;每个微服务都是独立的&#xff0c;好处自然很多&#xff0c;但是随着应用的越来越大&#xff0c;微服务暴露出来的问题也就随之而来了&#xff0c;微服务越来越多&a…

【Python】使用python解析普通格式的报文为someip格式报文

文章目录 1.安装scapy库2.示例 1.安装scapy库 使用 pip 安装 scapy 第三方库&#xff0c;打开 cmd&#xff0c;输入以下命令&#xff1a; pip install scapy出现如图所示&#xff0c;表示安装成功&#xff1a; 2.示例 要解析someip格式报文&#xff0c;需要导入someip模块&a…

【Spring 】了解Spring AOP

目录 一、什么是Spring AOP 二、AOP的使用场景 三、AOP组成 四、Spring AOP的实现 1、添加Spring AOP依赖 2、定义切面和切点 3、定义相关通知 五、 AOP的实现原理 1、什么是动态代理 2、 JDK代理和CGLIB代理的区别 一、什么是Spring AOP AOP&#xff08;Aspect Ori…

PLY模型格式详解【3D】

本文介绍PLY 多边形文件格式&#xff0c;这是一种用于存储被描述为多边形集合的图形对象。 PLY文件格式的目标是提供一种简单且易于实现但通用的格式足以适用于各种模型。 PLY有两种子格式&#xff1a;易于入门的 ASCII 表示形式和用于紧凑存储和快速保存和加载的二进制格式。 …

【FastColoredTextBox】C# 开源文本编辑控件

主界面截图 使用Demos演示 FastColoredTextBox 是一个用于在 C# 程序中实现高亮语法着色、代码编辑和文本显示的自定义控件。它提供了许多功能&#xff0c;包括&#xff1a; 语法高亮&#xff1a;FastColoredTextBox 支持多种语言的语法高亮&#xff0c;可以根据语法规则将不同…

write javaBean error, fastjson version 1.2.76

fastjson JSON.toJSONString 报错&#xff1a; > [0] JavaBeanSerializer.java->541: com.alibaba.fastjson.serializer.JavaBeanSerializer->write()> [1] JavaBeanSerializer.java->154: com.alibaba.fastjson.serializer.JavaBeanSerializer->write()>…

vite4+vue3+electron23.3+ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包

vite4vue3electron23.3ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包 主要包依赖 "electron-store": "^8.1.0", //全局数据状态管理&#xff0c;可选择性安装"electron": "23.3.8","electron-builder": &q…

Android 使用SQLite的案例详解

1、说明 sqlite是个轻量级的数据库,可用于嵌入式。有时候做本地的web开发的时候,我会把sqlite作为内置数据库,这样便于部署,直接启动应用即可。 这里主要是将android中的使用过程记录一下。主要包含,数据如何初始化,在不同的activity中如何使用,以及增删改查的实现。 …

网页显示摄像头数据的方法---基于web video server

1. 背景&#xff1a; 在ros系统中有发布摄像头的相关驱动rgb数据&#xff0c;需求端需要将rgb数据可以直接在网页上去显示。 问题解决&#xff1a; web_video_server功能包&#xff0c;相关链接&#xff1a; web_video_server - ROS Wiki 2. 下载&#xff0c;安装和编译&a…

Ubuntu20 ctrl+alt+T无法打开终端

事情是这样的&#xff0c;某天改了下python版本&#xff0c;发现linux默认打开终端的快捷键ctrlaltT寄了&#xff0c;网上给出的都是修改快捷键不出意外肯定没用 但是幸好我们是会分析的&#xff0c;我看到&#xff0c;很多回答说新增一个快捷键运行的命令是gnome-terminal&…

21、stm32使用LTDC驱动LCD

注&#xff1a;本文基于stm32使用FMC驱动SDRAM(IS42S32800G-6BLI)工程继续开发 本例使用安富莱的H743XIH板子驱动LTDC点亮7寸LCD 硬件接线&#xff1a;RGB888 一、cubemx配置 1、LTDC配置 注意此引脚应于上面的硬件接线图一致 2、配置DMA2D 3、背光引脚和触摸引脚 4、时钟…

在 IntelliJ IDEA 中使用 Docker 开发指南

目录 一、IDEA安装Docker插件 二、IDEA连接Docker 1、Docker for Windows 连接 2、SSH 连接 3、Connection successful 连接成功 三、查看Docker面板 四、使用插件生成镜像 一、IDEA安装Docker插件 打开 IntelliJ IDEA&#xff0c;点击菜单栏中的 "File" -&g…