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.rhkb.cn/news/284709.html

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

相关文章

软件测试 -- Selenium常用API全面解答(java)

写在前面 // 如果文章有问题的地方, 欢迎评论区或者私信指正 目录 什么是Selenium 一个简单的用例 元素定位 id定位 xpath定位 name定位 tag name 定位和class name 定位 操作元素 click send_keys submit text getAttribute 添加等待 显示等待 隐式等待 显示等…

【网络安全】CobaltStrike 使用

本文章仅用于信息安全学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若读者因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与作者无关。 Cobalt Strike是一款渗透测试神器&#xff0c;Cobalt Strike已经不再使用MSF而是作为单独的平台使…

[NLP] 初窥000001

NL(natural language)–自然语言 人类的语言–中文&#xff0c;英语&#xff0c;法语 NLP(Natural Language Processing)–自认语言处理 计算机处理人类语言的技术&#xff0c;它包含翻译、智能问答、文本分类、情感分析等常见应用。 CV(Computational Vision) 感知NLP 认知…

Vue使用font-face自定义字体详解

目录 1 介绍2 使用2.1 语法2.2 属性说明2.3 Vue使用案例2.3.1 全局定义字体2.3.2 在页面使用 3 注意事项 1 介绍 font-face 是 CSS 中的一个规则&#xff0c;它允许你加载服务器上的字体文件&#xff08;远程或者本地&#xff09;&#xff0c;并在网页中使用这些字体。这样&am…

【C语言】——指针四:字符指针与函数指针变量

【C语言】——指针四&#xff1a;字符指针与函数指针变量 一、字符指针二、函数指针变量2.1、 函数指针变量的创建2.2、两段有趣的代码 三、typedef关键字3.1、typedef的使用3.2、typedef与define比较 四、函数指针数组 一、字符指针 在前面的学习中&#xff0c;我们知道有一种…

LeetCode Python - 71. 简化路径

目录 题目描述解法运行结果 题目描述 给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 ‘/’ 开头&#xff09;&#xff0c;请你将其转化为更加简洁的规范路径。 在 Unix 风格的文件系统中&#xff0c;一个点&#xff08;.&…

【电气安全】ASCP电气防火限流式保护器/末端回路线路保护

为什么要使用电气防火限流式保护器&#xff1f; 应急管理部消防救援局统计&#xff0c;在造成电气火灾事故的原因中&#xff0c;最为主要的当为末端线路短路&#xff0c;在电气火灾事故中占比高达70%以上。如何效预防末端线路短路引发的电气火灾事故&#xff1f; 现阶段最为常…

jmeter断言使用方法

断言主流的有两种&#xff1a;响应断言、JSON断言 响应断言 1、http请求添加响应断言 2、三种作用域&#xff1a;第一种既作用主请求又作用子请求、只作用主请求、只作用子请求。我们默认选中间的仅作用主请求即可。 3、测试字段和匹配规则 测试字段一般选择响应文本即可&am…

Springboot家乡特色推荐系统

目录 背景 技术简介 系统简介 界面预览 背景 在当今这个网络迅猛发展的时代&#xff0c;计算机技术已经广泛应用于我们生活的每个角落&#xff0c;互联网在经济和日常生活等多个方面扮演着至关重要的角色&#xff0c;它已成为人们分享资源和快速交流信息的关键平台。在中国…

灯塔:CSS笔记(5)

定位&#xff1a; 1.标准流 1.块级元素独占一行->垂直布局 2.行内元素/行内块元素一行显示多个->水平布局 2.浮动 可以让原本垂直布局的 块级元素变成水平布局 3.定位 1.可以让元素自由的摆放在网页的任意位置 2.一般用于盒子之间的层叠情况 使用定位的步骤 1.…

基于python+vue超市货品信息管理系统flask-django-php-nodejs

在此基础上&#xff0c;结合现有超市货品信息管理体系的特点&#xff0c;运用新技术&#xff0c;构建了以 python为基础的超市货品信息管理信息化管理体系。首先&#xff0c;以需求为依据&#xff0c;根据需求分析结果进行了系统的设计&#xff0c;并将其划分为管理员和用户二种…

【前端寻宝之路】学习和使用表单标签和表单控件

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-cR8zvB8CkpxTk485 {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

函数作用域和块级作用域:JavaScript中的变量作用域解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

tabs自定义样式

使用el-tabs 去修改样式的话比较麻烦&#xff0c;索性直接用div来制作。 <div class"contain"><div class"tab_wrap"><div :class"[skew, first, active 1 ? isActive: ]" click"tabClick(1)"><span class&quo…

Linux(Centos)安装mysql 8 并且使用systemctl管理服务

1.下载mysql包 地址 MySQL :: Download MySQL Community Server (Archived Versions) 注&#xff1a;下载我圈住的减压之后里面会有tar.gz 再次减压才会是软件主体 2.安装和准备 yum -y install numactl 安装numactl tar -xvf mysql-8.0.30-el7-x86_64.tar 拆分 …

C语言操作符和数据类型的存储详解

CSDN成就一亿技术人 目录​​​​​​​ 一.操作符 一.算数操作符&#xff1a; 二.位移操作符&#xff1a; 三.位操作符&#xff1a; 四.赋值操作符&#xff1a; 五.单目操作符&#xff1a; 六.关系操作符&#xff1a; 七.逻辑操作符&#xff1a; 八.条件操作符&…

Docker 笔记(七)--打包软件生成镜像

目录 1. 背景2. 参考3. 文档3.1 使用docker container commit命令构建镜像3.1.1 [Docker官方文档-docker container commit](https://docs.docker.com/reference/cli/docker/container/commit/)Description&#xff08;概述&#xff09;Options&#xff08;选项&#xff09;Exa…

Golang案例开发之gopacket抓包三次握手四次分手(3)

文章目录 前言一、理论知识三次握手四次分手二、代码实践1.模拟客户端和服务器端2.三次握手代码3.四次分手代码验证代码完整代码总结前言 TCP通讯的三次握手和四次分手,有很多文章都在介绍了,当我们了解了gopacket这个工具的时候,我们当然是用代码实践一下,我们的理论。本…

图论基础|695. 岛屿的最大面积、1020. 飞地的数量、130. 被围绕的区域

695. 岛屿的最大面积 力扣题目链接(opens new window) 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0&#xff0…

何为布控球?布控球的分类对比

主要的分类有&#xff1a; 根据内部的主控板卡的系统分类&#xff0c;典型的是基于海思芯片的嵌入式LINUX系统的&#xff0c;一般出国标GB28181&#xff0c;另外一种是剑走偏锋的安卓系统的&#xff0c;需要把球机的输出YUV转换为UVC接入安卓主板&#xff0c;作为外接USB摄像头…