React函数组件Hook

问题: 相对于类组件, 函数组件的编码更简单, 效率也更高, 但函数组件不能有state (旧版)

解决: React 16.8版本设计了一套新的语法来让函数组件也可以有state

  • Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性

  • Hook也叫钩子,本质就是函数,能让你使用 React 组件的状态和生命周期函数...

  • Hook 语法 基本已经代替了类组件的语法

  • 后面的 React 项目就完全是用Hook语法了

Hook API 索引 – React 官方文档: Hook API 索引 – React

hook函数和普通函数的区别:

hook函数本身就是一个函数。react通过函数名来判断是普通函数还是hook函 数,以useXxx 格式命名的就是hook函数。

Hook函数使用原则:

1.不能在类组件中使用,不能在普通函数中使用

2.只能在函数组件中使用,或其他hook函数中使用【react提供的,第三方的,自定义的】

3..hook函数必须是数量确定的,不能写在逻辑判断中或后,不能写在循环中

4.应用时,一般写在顶级作用域的首行 使用场景

-----1.可以在函数组件中使用

let [msg, setMsg] = useState('')function clickHandler(){// let [count,setCount] = useState() // 普通函数会报错}

-----2.自定hook中可以使用其他hook

function useClickHandler(){let [count,setCount] = useState(0)}

-----3.如果函数名首字母大写,他会 认为是函数组件,也不会报错

 function ClickHandler(){let [count,setCount] = useState(0)}

1.useState()

作用:给函数组件添加状态

返回值:是一个数组,第一个元素是状态,第二个元素是设置状态的函数

语法:let [状态, 设置状态函数] = useState(初始值)

import React,{useState} from 'react'export default function App() {console.log('App render')let [count,setCount] = useState(0)return (<div><h3>App</h3><p>{count}</p><p><button onClick={()=>{setCount(1000)}}>count + 1</button></p></div>)
}

2.useEffect

作用:用来模拟函数组件的生命周期 componentDidMount、componentDidUpdate、ComponentWillUnmounted

2.1.用法:

useEffect(回调函数) : 没有第二个参数 模拟 componentDidMount + componentDidUpdate

useEffect(() => {console.log('useEffect') 
})
2.2.用法

useEffect(回调函数,[]) 只模拟 componentDidMount

 useEffect(()=>{console.log('useEffect')   // componentDidMount},[])
2.3.用法

useEffect(回调函数,[某 个自身状态(state) , 某个 外部状态(props), .......])

useEffect(() => { console.log('useEffect')}, [count])
2.4.用法

useEffect( return ()=>{ } )   模拟componentWillUnmount

useEffect(()=>{console.log('Test useEffect')return ()=>{ // componentWillUnmountconsole.log('destroy')}},[msg,money])

3.useRef

作用 :可以用它获取dom元素

1. 创建一个ref let divRef = useRef()

2. 绑定ref

3. 获取dom元素

import React, { useRef } from "react";
export default function App() {let divRef = useRef();return (<div><div ref={divRef}><h3>app</h3><button onClick={()=>{console.log(divRef.current);}}>获取DOM元素</button></div></div>);
}

4.useContext

作用 :获取从祖先组件传递给后代组件的数据

4.1.创建context对象

context.js 代码

import React from 'react'
// 1. 创建context对象,并暴露出去
const context = React.createContext() 
export default context
4.2.使用Provider组件包裹 组件, 并通过 value 绑定要传的数据

App.jsx 代码

import React from "react";
import Father from "./components/Father50";
import context from "./context";
export default function App() {return (// 2. 使用Provider包裹组件,并通过value绑定要传输的数据<context.Provider value={{ name: "App的内容" }}><div><h3>App</h3><hr /><Father /></div></context.Provider>);
}
4.3. 引入context对象
4.4.通过useContext处理context对象,获取祖先组件传递的数据
import React from 'react'// 3. 引入context对象
import context from '../context'
import { useContext } from "react";export default function Father() {// 4. 通过useContext处理context对象,获取祖先组件传递的数据let {name} = useContext(context)return (<div><h4>Father</h4><p>Father-context: {name}</p><hr /></div>)
}

5.useReducer

集中状态管理。相当于是简化版的 redux

import React, { useState } from 'react'
import { useReducer } from 'react'
const initalState = { count: 0, msg: 'atguigu' }
function reducer(state, action) {switch (action.type) {case 'inc':return {...state,count: state.count + 1}case 'dec':return {...state,count: state.count - 1}case 'add':return {...state,msg:state.msg + '+'}default:throw new Error('没有处理case')}
}
export default function App() {let [state, dispatch] = useReducer(reducer, initalState)return (<div><p>count: {state.count}</p><p>msg: {state.msg}</p><p><button onClick={()=>{dispatch({type:'inc'})}}>count + 1</button></p><p><button onClick={()=>{dispatch({type:'add'})}}>msg + '+'</button></p></div>)
}

6.useCallBack

可以缓存一个函数。避免函数的多次创建。性能优化

用法一:

没有第二个参数,函数仍然会被重复创建

  let clickHandler = useCallback(() => {setCount(count + 1);});

用法二:

第二个参数是空数组,那么函数会被缓存

    let clickHandler = useCallback(()=>{// setCount(count + 1)// 函数被缓存,可以使用setXxx 第二种用法,获取最新的状态值setCount(count=>count + 1)},[])

用法三:

第二个参数是数组,并监听 x 个 状态,当这些状态中的一个或多个发生变化时,重新创建函数

  let clickHandler = useCallback(() => {setCount(count + 1);// 函数被缓存,可以使用setXxx 第二种用法,获取最新的状态值// setCount(count=>count + 1)}, [count]);

7.React.memo

作用:类似于类组件中的纯组件。当自身状态和外部数据没有变化的时候,不会重新渲染

App.jsx 代码

import React, { Component } from 'react'
import Test from './components/Test56'
export default class App extends Component {state = {msg:'React'}render() {console.log('App render')return (<div><h3>App</h3><p>msg: {this.state.msg}</p><p><button onClick={()=>this.setState({msg:'React'})}>msg change</button></p><hr /><Test msg={this.state.msg}/></div>)}
}

 Test.jsx 代码

import React from 'react'
import { useState } from 'react'function Test({msg}) {console.log('Test render')// useState已经对自身状态做过优化let [count,setCount] = useState(0)return (<div><p>count:{count}</p><p>App-msg: {msg}</p><button onClick={()=>{setCount(100)}}>count + 1</button></div>)
}export default React.memo(Test)

如图所示:

8.useMemo

作用:缓存一个函数计算的结果,常用来跟useCallback进行比较;useCallback是缓存一个 函数,useMemo缓存函数执行的结果

通俗来讲就是:它是一个优化性能的 Hook,它会记住函数的返回值,只要依赖项(dependency array)没有变化,就会复用之前的计算结果,避免在每次渲染时都重新执行这个可能开销较大的计算

官方详解:

App.jsx 代码

import React from 'react'
import Test from './components/Test57'export default function App() {return (<div><Test/></div>)
}

Tset.jsx 代码

import React, { useState,useMemo } from 'react';export default function Test() {
const [count,setCount] = useState(0)
const [val,setVal] = useState(0)const expensive = useMemo(()=>{console.log('================');let sum =0for(let i=1;i<count;i++){sum += i}return sum
},[count])// const expensive = (()=>{
//     console.log('================');
// },[count])return <div><h4>{count}-{val}-{expensive}</h4><div><button onClick={()=>setCount(count + 1)}>+c1</button><input val={val} onChange={event =>{setVal(event.target.value)}}/></div></div>;
}

9.useImperativeHandle

它与 forwardRef 结合使用以暴露自定义组件的 refs 给父组件。可以在使用 `ref` 时自定义暴露给父组件的实例值

官方文档:useImperativeHandle – React

APP.jsx 代码

import React from 'react'
import { useRef } from 'react'
import FunTest from './components/FunTest58'export default function App() {// ref可以给绑定类组件,并且可以获取类组件实例对象let refClass = useRef()// ref本身不能够给函数组件使用,但是可以通过 React.forwardRef()进行扩展let refFn = useRef('true')/*** 当希望在父组件获取子组件的dom对象的时候,可以使用 函数组件配合 React.forwardRef()实现*/return (<div><FunTest ref={refFn} /><p><button onClick={() => {console.log(refClass)console.log(refFn)}}>获取ref</button></p><p><button onClick={() => {refFn.current.changeBg()}}>changeBg</button></p><p><button onClick={() => {refFn.current.changeFontSize()}}>changeBg</button></p></div>)
}

FunTest.jsx 代码

import React from "react";
import { useRef, useImperativeHandle } from "react";function FunTest(props, AppRef) {let selRef = useRef()useImperativeHandle(AppRef,()=>({changeBg:()=>{selRef.current.style.backgroundColor = "red"}}))return (<div><h3 ref={selRef}>FunTest</h3></div>);
}
export default React.forwardRef(FunTest);

 如图所示:

10.useLayoutEffect

useLayoutEffect是useEffect的一个版本,在浏览器重新绘制屏幕之前触发。

useEffect在render结束后,你的callback函数执行,但是不会阻塞浏览器渲染

作用:用在处理DOM的时候,当你的useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否 则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在 浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制

官方文档:useLayoutEffect – React

App.jsx 代码

import React from 'react'
import Animate from './components/Animate59'export default function App() {return (<div><Animate/></div>)
}

Animate.jsx 代码

import React, { useEffect, useLayoutEffect, useRef } from 'react'
import TweenMax from 'gsap' // npm i gsap@3.7.0
import '../index.css'const Animate = () => {const REl = useRef(null)useLayoutEffect(()=>{TweenMax.to(REl.current,0,{x:600})},[])return (<div className="animate"><div ref={REl} className="square">square</div></div>)
}
export default Animate

11.useDebugValue

作用:用于在 React 开发者工具中显示 自定义 hook 的标签,只能在自定义hook中使用

官方文档:useDebugValue – React

12.useId

用于生成一个唯一的标识

import React from 'react'
import { useId } from 'react'export default function App() {let id1 = useId()let id2 = useId()console.log(id1);console.log(id2);return (<div><div>App</div></div>)
}

 

13.useTransition

作用:可以将任务设置为非紧急任务

官方文档:useTransition – React

const [isPending, startTransition] = useTransition()
startTransition(()=>{})

14.useDeferredValue

作用:根据一个状态,设置一个延时的状态。也可以实现,任务渲染的优先级区别

import { useState, useDeferredValue } from 'react';function SearchPage() {const [query, setQuery] = useState('');const deferredQuery = useDeferredValue(query);// ...
}

15.自定义hook函数

作用: 函数组件代码逻辑复用的手段,函数名 useXxx 格式 ,函数中可以使用其他hook函数

App.jsx 代码

import React, {useState} from 'react'
import { useEffect } from 'react'
import usePosition from '../hook/usePosition'
export default function Cat() {let {x,y} = usePosition()return (<div style={{width:100,height:100,border:'1px solid red',position:'absolute',left:x,top:y}}>Cat</div>)
}

 usePosition.js 代码

import {useState, useEffect} from 'react'
export default function usePosition() {let [x, setX] = useState(0)let [y, setY] = useState(0)function moveHandler(e) {setX(e.clientX)setY(e.clientY)}useEffect(() => {window.addEventListener('mousemove', moveHandler)return () => {window.removeEventListener('mousemove', moveHandler)}}, [])return {x,y}
}

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

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

相关文章

Simple negative sampling for link prediction inknowledge graphs

摘要 知识图嵌入方法学习知识图中实体和关系的低维向量表示&#xff0c;便于知识图中的链接预测任务。在学习嵌入过程中&#xff0c;采样负三元组是很重要的&#xff0c;因为KGs只观察到正三元组。据我们所知&#xff0c;均匀随机、基于生成对抗网络(GAN)和nscach、结构感知负…

Linux 系统 快速卸载docker

(卸载前一定要做好相关数据的备份) 卸载&#xff1a; 第一种卸载方法 1、查询docker安装过的包&#xff1a; yum list installed | grep docker 2、删除安装包&#xff1a; yum remove docker-ce.x86_64 ddocker-ce-cli.x86_64 -y 3、删除镜像/容器等 rm -rf /var/lib/dock…

【征稿进行时|见刊、检索快速稳定】2024年教育资源与人文发展国际学术会议(ICERHD 2024)

【征稿进行时|见刊、检索快速稳定】2024年教育资源与人文发展国际学术会议&#xff08;ICERHD 2024&#xff09; 2024 International Conference on Educational Resources and Humanistic Development&#xff08;ICERHD 2024&#xff09; 大会主题&#xff1a; 教育艺术 商…

机器学习周报第33周

目录 摘要Abstract一、文献阅读1.1 论文标题1.2 论文摘要1.3 论文背景1.4 过去研究1.5 论文介绍1.5.1 论文模型1.5.2 时空交互学习模块&#xff08;Spatiotemporal Interactive Learning Module&#xff09;1.5.3 动态图推理模块&#xff08;Dynamic Graph Inference Module&am…

【Java】基于SpringCloud的考研复试辅导平台

1、前端请求后端服务提供的接口。 2、后端服务的控制层Controller接收前端的请求。 3、Contorller层调用Service层进行业务处理。 4、Service层调用Dao持久层对数据持久化。 XXX-api&#xff1a;接口工程&#xff0c;为前端提供接口。 XXX-service: 业务工程&#xff0c;为…

SQLite使用的临时文件(二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite数据库文件损坏的可能几种情况 下一篇&#xff1a;未发表 ​ 1. 引言 SQLite的显着特点之一它是一个数据库由一个磁盘文件组成。 这简化了 SQLite 的使用&#xff0c;因为移动或备份 数据库就像复制单个文…

shell编程-jq命令详解

文章目录 前言一、jq简介1. 简介2. 语法3. 命令选项 二、用于处理json数据1. 过滤1.1 标识运算符1.2 基本过滤1.3 获取对象属性1.3 迭代数组元素1.4 获取数组元素1.5 使用运算符 2. 类型和值2.1 数组构造2.2 对象构造2.3 递归下降 3. 内置运算符和函数3.1 算术运算符3.2 函数3.…

PCL点云处理之最小中值平方(Lmeds法)拟合平面(二百三十四)

PCL点云处理之 最小中值平方法(Lmeds)拟合平面(二百三十四) 一、算法介绍一、拟合原理二、具体实现1.代码2.结果一、算法介绍 (本文提供详细注释,输出拟合平面参数和平面点云) Lmeds(Least Median of Squares)是一种统计学方法,用于拟合数据并减少异常值对拟合结果…

基础篇Redis

基础篇Redis 1.Redis简单介绍 Redis是一种键值型的NoSql数据库&#xff0c;这里有两个关键字&#xff1a; 键值型NoSql 其中键值型&#xff0c;是指Redis中存储的数据都是以key.value对的形式存储&#xff0c;而value的形式多种多样&#xff0c;可以是字符串.数值.甚至json…

前端-html-01

1.HTML的标签分类 1.1常用排版标签 标签名语义和功能属性单标签还是双标签h1 ~ h6一级标题~六级标题无双标签p段落无双标签hr分隔线无单标签br换行无单标签pre原格式显示无双标签div无语义&#xff0c;用于页面布局无双标签 1.1.1h标题标签 <!DOCTYPE html> <htm…

Redis I/O多路复用

I/O多路复用 Redis的I/o多路复用中&#xff0c;将多个连接放到I/O复用程序中&#xff0c;这个复用程序具体是什么&#xff0c;是Redis的主线程吗 在Redis的I/O多路复用机制中&#xff0c;“复用程序”实际上指的是操作系统提供的系统调用接口&#xff0c;如Linux下的epoll、sel…

ZYNQ学习之Ubuntu环境下的Shell与APT下载工具

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ 一、Ubuntu Shell操作 简单的说Shell 就是敲命令。国内把 Linux 下通过命令行输入命令叫…

如何本地搭建群晖虚拟机并实现无quickconnect服务环境远程访问

文章目录 前言本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是前排提醒&#xff1a; 1. 搭建群晖虚拟机1.1 下载黑群晖文件vmvare虚拟机安装包1.2 安装VMware虚拟机&#xff1a;1.3 解压黑群晖虚拟机文件1.4 虚拟机初始化1.5 没有搜索到黑群晖的解…

解密Google Cloud 全新 PaLM2及创新应用

&#x1f4f8;背景 因长期在大模型相关的部门工作&#xff0c;每天接收到很多和AI相关的信息&#xff0c;但小编意识到目前理解到的一些AI知识还有些片面。 恰逢稀土掘金开发者大会有谈到大模型相关的知识&#xff0c;于是借此机会&#xff0c;对大模型相关的一些知识再了解一…

【SpringCloud】探索Eureka注册中心

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

Protobuf基础使用

Protobuf是什么 在我们日常编写代码的过程中&#xff0c;经常会涉及到网络传输的部分。我们通常会在网络之间传递各种各样的请求&#xff0c;但是在我们日常架构之中&#xff0c;经常会涉及后端服务器之间的通信&#xff0c;通信过程中&#xff0c;可能传递的对象就是一个类。…

【vscode打开多文件夹】

1)将文件夹添加到工作空间中 2)文件夹方式展开 3)最终效果 小技巧&#xff1a; 文件夹的位置不对的话&#xff0c;可以拖动进行调整。

Linux--动静态库的原理和使用详解

本文介绍了Linux系统中动态库与静态库的概念、原理以及使用方法。通过深入讲解动态库与静态库的区别和优劣势&#xff0c;帮助读者更好地理解并选择合适的库类型来进行软件开发。 动态库和静态库的概念 动态库&#xff08;Dynamic Link Library&#xff0c;简称DLL&#xff09…

优化金融展厅设计,细节提升客户体验与实用效能

“很赚钱”大部分公众对金融行业的第一印象&#xff0c;这足以见得金融行业在社会经济发展中的重要性&#xff0c;而为了更好的宣传和科普金融相关信息&#xff0c;金融展厅的设计和建设成为了重要措施&#xff0c;它能够充分展示金融机构的实力、品牌形象和服务优势&#xff0…

Jmeter使用BeanShell保存数据到文件

1、目的 在使用jmeter压测时&#xff0c;业务上下连贯&#xff0c;需要对一些编号进行关联操作。这里使用‘JSON提取器’将值提取出来&#xff0c;后面请求可以直接使用。其它业务想要使用就只能把值保存到文件&#xff0c;再使用文件做参数化了。 2、JSON提取器 提取请求值 提…