常见React Hooks 钩子函数用法

一、useState

useState()用于为函数组件引入状态(state)。纯函数不能有状态,所以把状态放在钩子里面。

import React, { useState } from 'react'
import './Button.css'export function UseStateWithoutFunc() {const [name, setName] = useState('何遇')const [age, setAge] = useState()function onChange() {setName('张三') // 修改namesetAge(23) // 修改age}return (<><div className={'nameButton'}>姓名: {name}</div><div className={'ageButton'}>年龄: {age === undefined ? '未知' : age}</div><button onClick={onChange}>click</button></>)
}

上面代码中,UseStateWithoutFunc 组件是一个函数,内部使用useState()钩子引入状态。

useState()这个函数接受状态的初始值,作为参数,上例的初始值为显示的姓名文字。该函数返回一个数组,数组的第一个成员是一个变量(上例是name),指向状态的当前值。第二个成员是一个函数,用来更新状态,约定是set前缀加上状态的变量名(上例是setName)。

当没有赋予初始值的时候,这个变量则是undefined,没有定义的。当再次执行set函数的时候,则会被赋值。如上述年龄字段age,一开始是undefined的,所以显示出来的效果就是“未知”。

当点击button的时候,触发onChange函数,同时给年龄和姓名赋新值。因此点击按钮之后显示效果如下:

二、useEffect

seEffect()用来引入具有副作用的操作,最常见的就是向服务器请求数据。以前,放在componentDidMount里面的代码,现在可以放在useEffect()。

useEffect()的用法如下:

useEffect(() => {// Async Action
}, [dependencies]); 

上面用法中,useEffect()接受两个参数。

  • 第一个参数是一个函数,异步操作的代码放在里面。
  • 第二个参数是一个数组,用于给出 Effect 的依赖项,只要这个数组发生变化,useEffect()就会执行。第二个参数可以省略,这时每次组件渲染时,就会执行useEffect()。

下面是Person.js和Person.css代码

import {useEffect, useState} from "react";
import "./Person.css";const Person = ({personId}) => {const[loading, setLoading] = useState(true);const[person, setPerson] = useState({});useEffect(() => {setLoading(true);fetch(`https://swapi.dev/api/people/${personId}`).then(response => response.json()).then(data => {setLoading(false)setPerson(data)});}, [personId]);if (loading) {return <p>Loading...</p>}return <div><p>You're viewing: {person.name}</p><p>Height: {person.height}</p><p>Mass: {person.mass}</p></div>
}export default function PersonComponent() {const [show, setShow] = useState("1");return (<div className="App"><Person personId={show}></Person><div>Show:<button onClick={() => setShow("3")}>R2-D2</button><button onClick={() => setShow("2")}>C-3PO</button></div></div>)
}
* {margin: 0;padding: 0;
}
body {padding: 10px;background-color: #f5f5fa;color: #222;
}
h2 {margin-bottom: 20px;font-family: 'Helvetica';font-weight: 400;
}
.App {font-family: 'Helvetica';font-weight: 200;text-align: left;width: 400px;
}
input {border: 1px solid #ddd;background-color: #fff;padding: 5px 10px;margin: 10px 0;border-radius: 5px;width: 300px;
}
button {padding: 5px 20px;background: #0066cc;border: 1px solid #fff;border-radius: 15px;color: #fff;margin-top: 10px;margin-bottom: 10px;
}
button:hover {cursor: pointer;box-shadow: 0px 2px 4px #0044aa40;
}
button:active {background: #0044aa;
}
button:focus {outline:0;}
ul {margin-left: 20px;
}.navbar {display: flex;flex-direction: row;justify-content: space-between;padding-bottom: 10px;margin-bottom: 20px;border-bottom: 1px solid #ccc;
}
.messages h1 {margin-bottom: 20px;
}
.messages p {margin-bottom: 10px;
}
.message {background-color: #fff;border: 1px solid #ddd;padding: 10px;border-radius: 4px;
}

在请求https://swapi.dev/api/people/{personId}/ 这个接口,每次传入不同的personId值,就可以请求到不同人的数据。

每次personId发生改变之后,Person组件里的useEffect里的方法就会执行一次也就是会去请求一次后端数据,请求到了之后再刷新界面。没有请求到的时候由于loading默认设为true,因此就会执行return <p>Loading...</p>这段代码,就会展示Loading的文字。等请求到之后,会执行这行 setLoading(false),将loading字段设为false,因此此时就不会展示Loading的文字,而是展示姓名、身高等字样。

点击R2-D2数据还没请求到的时候,会显示Loading

请求到对应的数据之后,就会展示对应的个人信息

三、useReducer

React 本身不提供状态管理功能,通常需要使用外部库。这方面最常用的库是 Redux。

Redux 的核心概念是,组件发出 action 与状态管理器通信。状态管理器收到 action 以后,使用 Reducer 函数算出新的状态,Reducer 函数的形式是(state, action) => newState。

useReducers()钩子用来引入 Reducer 功能。

const [state, dispatch] = useReducer(reducer, initialState);

上面是useReducer()的基本用法,它接受 Reducer 函数和状态的初始值作为参数,返回一个数组。数组的第一个成员是状态的当前值,第二个成员是发送 action 的dispatch函数。

下面是一个计数器的例子。用于计算状态的 Reducer 函数如下。

const myReducer = (state, action) => {switch(action.type)  {case('countUp'):return  {...state,count: state.count + 1}default:return  state;}
}

组件代码如下。

export default function UseReducerComponent() {const[state, dispatch] = useReducer(myReducer, {count: 0})return (<div className="App"><button onClick={() => dispatch({type: 'countUp'})}>+1</button><p>Count: {state.count}</p></div>)
}

import {useReducer} from "react";
import "./styles.css";const myReducer = (state, action) => {switch (action.type) {case ('countUp'):return {...state,count: state.count + 1}default:return state}
}export default function UseReducerComponent() {const[state, dispatch] = useReducer(myReducer, {count: 0})return (<div className="App"><button onClick={() => dispatch({type: 'countUp'})}>+1</button><p>Count: {state.count}</p></div>)
}

styles.css样式如下:

* {margin: 0;padding: 0;
}
body {padding: 10px;background-color: #f5f5fa;color: #222;
}
h2 {margin-bottom: 20px;font-family: 'Helvetica';font-weight: 400;
}
.App {font-family: 'Helvetica';font-weight: 200;text-align: left;width: 400px;
}
input {border: 1px solid #ddd;background-color: #fff;padding: 5px 10px;margin: 10px 0;border-radius: 5px;width: 300px;
}
button {padding: 5px 20px;background: #0066cc;border: 1px solid #fff;border-radius: 15px;color: #fff;margin-top: 10px;margin-bottom: 10px;
}
button:hover {cursor: pointer;box-shadow: 0px 2px 4px #0044aa40;
}
button:active {background: #0044aa;
}
button:focus {outline:0;}
ul {margin-left: 20px;
}.navbar {display: flex;flex-direction: row;justify-content: space-between;padding-bottom: 10px;margin-bottom: 20px;border-bottom: 1px solid #ccc;
}
.messages h1 {margin-bottom: 20px;
}
.messages p {margin-bottom: 10px;
}
.message {background-color: #fff;border: 1px solid #ddd;padding: 10px;border-radius: 4px;
}

四、useContext

如果需要在组件之间共享状态,可以使用useContext()。

现在有两个组件 Navbar 和 Messages,我们希望它们之间共享状态。

<div className="App"><Navbar/><Messages/>
</div>

第一步就是使用 React Context API,在组件外部建立一个 Context。

const AppContext = React.createContext({});

组件封装代码如下。

<AppContext.Provider value={{username: 'superawesome'
}}><div className="App"><Navbar/><Messages/></div>
</AppContext.Provider>

上面代码中,AppContext.Provider提供了一个 Context 对象,这个对象可以被子组件共享。

Navbar 组件的代码如下。下面代码中,useContext()钩子函数用来引入 Context 对象,从中获取username属性

const Navbar = () => {const { username } = useContext(AppContext);return (<div className="navbar"><p>AwesomeSite</p><p>{username}</p></div>);
}

Message 组件的代码如下。下面代码中,useContext()钩子函数用来引入 Context 对象,从中获取username属性

const Messages = () => {const { username } = useContext(AppContext)return (<div className="messages"><h1>Messages</h1><p>1 message for {username}</p><p className="message">useContext is awesome!</p></div>)
}

UseContextComponent.js代码如下所示:

import React, { useContext } from "react";
import "./style.css";const AppContext = React.createContext({});const Navbar = () => {const { username } = useContext(AppContext)return (<div className="navbar"><p>AwesomeSite</p><p>{username}</p></div>)
}const Messages = () => {const { username } = useContext(AppContext)return (<div className="messages"><h1>Messages</h1><p>1 message for {username}</p><p className="message">useContext is awesome!</p></div>)
}export default function UseContextComponent() {return (<AppContext.Provider value={{username: 'superawesome'}}><div className="App"><Navbar /><Messages /></div></AppContext.Provider>);
}

style.css文件如下:

* {margin: 0;padding: 0;
}
body {padding: 10px;background-color: #f5f5fa;color: #222;
}
h2 {margin-bottom: 20px;font-family: 'Helvetica';font-weight: 400;
}
.App {font-family: 'Helvetica';font-weight: 200;text-align: left;width: 400px;
}
input {border: 1px solid #ddd;background-color: #fff;padding: 5px 10px;margin: 10px 0;border-radius: 5px;width: 300px;
}
button {padding: 5px 20px;background: #0066cc;border: 1px solid #fff;border-radius: 15px;color: #fff;margin-top: 10px;margin-bottom: 10px;
}
button:hover {cursor: pointer;box-shadow: 0px 2px 4px #0044aa40;
}
button:active {background: #0044aa;
}
button:focus {outline:0;}
ul {margin-left: 20px;
}.navbar {display: flex;flex-direction: row;justify-content: space-between;padding-bottom: 10px;margin-bottom: 20px;border-bottom: 1px solid #ccc;
}
.messages h1 {margin-bottom: 20px;
}
.messages p {margin-bottom: 10px;
}
.message {background-color: #fff;border: 1px solid #ddd;padding: 10px;border-radius: 4px;
}

可以理解为一种共享上下文状态。类似于Android里context的一样,获取上下文信息的。

第一块是组件Navbar展示的

第二块是组件Message展示的

引用文献:

【1】轻松学会 React 钩子:以 useEffect() 为例 - 阮一峰的网络日志

【2】React Hooks 入门教程 - 阮一峰的网络日志

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

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

相关文章

了解高防服务器的工作原理

在当今互联网时代&#xff0c;网络安全问题日益突出&#xff0c;各种网络攻击层出不穷。为了保护企业的网络安全&#xff0c;高防服务器应运而生。那么&#xff0c;你是否了解高防服务器的工作原理呢?下面就让我们一起来探索一下。 高防服务器是一种能够有效抵御各种网络攻击的…

Bun 1.0.7 版本发布,实现多个 Node.js 兼容改进

导读Bun 是一个集打包工具、转译器和包管理器于一体的 JavaScript 运行时&#xff0c;由 Jarred Sumner 发布了 1.0.7 版本。本次更新实现了对 Node.js 运行时的多项兼容性改进&#xff0c;并修复了近 60 个 bug。 根据发布说明&#xff0c;本版本对 “bun install” 命令进行…

uview组件u-tabs添加badge数字消息提醒

效果图 在slot插槽中&#xff0c;使用v-if指令来判断当前选项卡是否是当前激活的选项卡&#xff08;即index是否等于currentTab&#xff09;&#xff0c;以及徽标数是否大于0。 <view><u-tabs:list"listTab" //标题数据:is-scroll"false":curre…

【C++初阶】一、入门知识讲解(C++关键字、命名空间、C++输入输出、缺省参数、函数重载)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【数据结构初阶】十一、归并排序(比较排序)的讲解和实现 &#xff08;递归版本 非递归版本 -- C语言实现&#xff09;-CSDN博客 引言&#xff1a;什么是C C语言是结构化和模块化的…

pytest全局变量的使用

这里重新阐述下PageObject设计模式&#xff1a; PageObject设计模式是selenium自动化最成熟&#xff0c;最受欢迎的一种模式&#xff0c;这里用pytest同样适用 这里直接提供代码&#xff1a; 全局变量 conftest.py """ conftest.py 全局变量&#xff0c;主要实…

探索ChatGPT在学术写作中的应用与心得

随着人工智能的迅猛发展&#xff0c;ChatGPT作为一种强大的自然语言处理模型&#xff0c;逐渐在学术界引起了广泛的关注。本文将探讨ChatGPT在学术写作中的应用&#xff0c;并分享使用ChatGPT进行学术写作时的一些经验和心得。 01 — ChatGPT在学术写作中的应用 1.文献综述和…

高速串行总线——SATA

SATA简介 SATA的全称是Serial Advanced Technology Attachment(串行高级技术附件&#xff0c;一种基于行业标准的串行硬件驱动器接口)&#xff0c;它是一种电脑总线&#xff0c;主要功能是用作主板和大量存储设备&#xff08;如硬盘及光盘驱动器&#xff09;之间的数据传输 SA…

挑战100天 AI In LeetCode Day04(热题+面试经典150题)

挑战100天 AI In LeetCode Day04&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-62.1 题目2.2 题解 三、面试经典 150 题-63.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&am…

Flink SQL Window TopN 详解

Window TopN 定义&#xff08;⽀持 Streaming&#xff09;&#xff1a; Window TopN 是特殊的 TopN&#xff0c;返回结果是每⼀个窗⼝内的 N 个最⼩值或者最⼤值。 应⽤场景&#xff1a; TopN 会出现中间结果&#xff0c;出现回撤数据&#xff0c;Window TopN 不会出现回撤数据…

蓝桥杯每日一题2023.11.5

题目描述 方格分割 - 蓝桥云课 (lanqiao.cn) 题目分析 对于每个图我们可以从中间开始搜索&#xff0c;如果到达边界点就说明找到了一种对称的方法&#xff0c;我们可以直接对此进行答案记录每次进行回溯就会找到不同的图像&#xff0c;如果是一样的图像则算一种情况&#xff…

[Kettle] Excel输入

Excel文件采用表格的形式&#xff0c;数据显示直观&#xff0c;操作方便 Excel文件采用工作表存储数据&#xff0c;一个文件有多张不同名称的工作表&#xff0c;分别存放相同字段或不同字段的数据 数据源 物理成绩(Kettle数据集2).xls https://download.csdn.net/download/H…

AI智能公文写作助手“文山会海“

公文写作痛点 没思路&#xff0c;公文写作无从下手公文类型繁多&#xff0c;一时难以全面掌握公文内容组织难度大&#xff0c;不易清晰、有逻辑的进行表达时间紧任务急&#xff0c;往往需要在有限的时间内完成大量写作工作反复修改优化&#xff0c;需满足更多新要求&#xff0…

Linux学习之vim跳转到特定行数

参考的博客&#xff1a;《Vim跳到最后一行的方法》 《oeasy教您玩转vim - 14 - # 行头行尾》 《Linux&#xff1a;vim 中跳到首行和最后一行》 想要跳到特定行的话&#xff0c;可以在命令模式和正常模式进行跳转。要是对于vim的四种模式不太熟的话&#xff0c;可以到博客《Linu…

使用VSCODE链接Anaconda

打代码还是在VSCODE里得劲 所以得想个办法在VSCODE里运行py文件 一开始在插件商店寻找插件 但是没有发现什么有效果的 幸运的是VSCODE支持自己选择Python的解释器 打开VSCODE 按住CtrlShiftP 输入Select Interpreter 如果电脑已经安装上了Python的环境 VSCODE会默认选择普通…

Redis中的渐进式遍历-Scan命令

之前我们学习过遍历命令keys,而keys *是一次性的把整个redis中所有的key都获取到.在不知道当前redis中有多少key的情况下,这个操作是非常危险的,可能会一下子得到太多的key而阻塞redis服务器.从而使其他redis客户端卡顿. 通过渐进式遍历,就可以做到,既可以获取到所有的key,同时…

视频集中存储EasyCVR平台播放一段时间后出现黑屏是什么原因?该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

零代码编程:用ChatGPT批量提取flash动画swf文件中的mp3

文件夹&#xff1a;C:\迅雷下载\有声绘本_flash[淘宝-珍奥下载]\有声绘本 flash&#xff0c;里面有多个flash文件&#xff0c;怎么转换成mp3文件呢? 可以使用swfextract工具从Flash动画中提取音频&#xff0c;下载地址是http://www.swftools.org/download.html&#xff0c;也…

Python学习-shutil模块和OS模块学习

shutil模块 针对文件的拷贝&#xff0c;删除&#xff0c;移动&#xff0c;压缩和解压操作 # 1.copyfileobj只能复制文件内容&#xff0c;无法复制权限#复制文件时&#xff0c;要选择自己有权限的目录执行操作&#xff0c;创建的文件会根据系统umask设定的参数来指定用户权限 s…

理解交叉熵(Cross Entropy)

交叉熵&#xff08;Cross-Entropy&#xff09;是一种用于衡量两个概率分布之间的距离或相似性的度量方法。在机器学习中&#xff0c;交叉熵通常用于损失函数&#xff0c;用于评估模型的预测结果与实际标签之间的差异。 在分类问题中&#xff0c;交叉熵损失函数通常用于多分类问…

项目构建工具maven的基本配置+idea 中配置 maven

&#x1f451; 博主简介&#xff1a;知名开发工程师 &#x1f463; 出没地点&#xff1a;北京 &#x1f48a; 2023年目标&#xff1a;成为一个大佬 ——————————————————————————————————————————— 版权声明&#xff1a;本文为原创文…