React函数组件Hook

news2024/12/25 9:52:20

问题: 相对于类组件, 函数组件的编码更简单, 效率也更高, 但函数组件不能有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 ()=>{ // componentWillUnmount
 console.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 =0
    for(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.coloradmin.cn/o/1532887.html

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

相关文章

从边缘设备丰富你的 Elasticsearch 文档

作者&#xff1a;David Pilato 我们在之前的文章中已经了解了如何丰富 Elasticsearch 本身和 Logstash 中的数据。 但如果我们可以从边缘设备中做到这一点呢&#xff1f; 这将减少 Elasticsearch 要做的工作。 让我们看看如何从具有代理处理器的 Elastic 代理中执行此操作。 E…

Introduction to Data Mining 数据挖掘

Why Data Mining? • The Explosive Growth of Data: from terabytes to petabytes — Data collection and data availability ◦ Automated data collection tools, database systems, Web, computerized society — Major sources of abundant data ◦ Business: Web, e-co…

Linux-shell中变量的引用($变量名,${变量名})

1. 背景 最近写脚本时&#xff0c;发现有个变量在某个地方生效&#xff0c;某个地方又不生效&#xff0c;引用方式为 $变量名。 2. 方法 其实 shell 脚本中对变量的引用有两种方式&#xff1a; $变量名${变量名} 用下面的脚步&#xff0c;去测试效果&#xff1a; a100 b2…

excel处理_多个excel文件合并

data文件夹内&#xff0c;有多个xls文件。每个xls文件格式一致&#xff0c; 表头占两行&#xff0c;表位汇总数据占一行。 表头两行&#xff0c;拼接前第二行设置为表头&#xff0c;且删除第二行。 在python读入的dataframe中&#xff0c;游轮成本表是表头&#xff0c;第一行是…

Python 深度学习第二版(GPT 重译)(四)

九、高级计算机视觉深度学习 本章涵盖 计算机视觉的不同分支&#xff1a;图像分类、图像分割、目标检测 现代卷积神经网络架构模式&#xff1a;残差连接、批量归一化、深度可分离卷积 可视化和解释卷积神经网络学习的技术 上一章通过简单模型&#xff08;一堆Conv2D和MaxP…

【鸿蒙HarmonyOS开发笔记】通知模块之为通知添加行为意图

概述 WantAgent提供了封装行为意图的能力&#xff0c;这里所说的行为意图主要是指拉起指定的应用组件及发布公共事件等能力。HarmonyOS支持以通知的形式&#xff0c;将WantAgent从发布方传递至接收方&#xff0c;从而在接收方触发WantAgent中指定的意图。例如&#xff0c;在通…

js【详解】深拷贝

什么是深拷贝&#xff1f; 对于引用类型的数据&#xff0c;才有深浅拷贝的说法 浅拷贝 &#xff1a;执行拷贝的变量只复制被拷贝变量内存的引用数据的地址。 被拷贝变量内地址指向的数据发生变化时&#xff0c;执行拷贝的变量也会同步改变 深拷贝&#xff1a; 在堆内存中开…

迁移学习的技术突破与应用前景

目录 前言1 迁移学习技术1.1 原理与分类1.2 主要挑战 2 迁移学习应用2.1 计算机视觉2.2 医疗健康 3 未来展望3.1 推动各领域发展3.2 提高模型泛化能力和效果3.3 在新兴领域中广泛应用 结语 前言 迁移学习作为机器学习领域的重要技术之一&#xff0c;以其能够将从一个任务中学到…

[C语言]——内存函数

目录 一.memcpy使用和模拟实现&#xff08;内存拷贝&#xff09; 二.memmove 使用和模拟实现 三.memset 函数的使用&#xff08;内存设置&#xff09; 四.memcmp 函数的使用 C语言中规定&#xff1a; memcpy拷贝的就是不重叠的内存memmove拷贝的就是重叠的内存但是在VS202…

腾讯和香港中文大学发布文字生成视频AI模型DynamiCrafter

前言 在数字化时代&#xff0c;视觉内容的创造和动态化已成为创意表达和信息传递的重要工具。最近由香港中文大学、腾讯AI Lab联合研发的视频AI模型DynamiCrafter&#xff0c;这一模型能够将静态图像转化为逼真的动态视频&#xff0c;开创了文本到视频生成技术的新纪元。 Hugg…

Nexus介绍

1.什么是Nexus Nexus是一个强大的仓库管理器&#xff0c;主要用于搭建和管理公司内部的软件构件仓库。 以下是一些关于Nexus的重要信息&#xff1a; 功能&#xff1a;Nexus可以作为Maven、NuGet、npm等工具的仓库服务器&#xff0c;允许用户在本地网络中共享和管理依赖项和构…

计算机三级——网络技术(综合题第二题)

路由器工作模式 用户模式 当通过Console或Telnet方式登录到路由器时&#xff0c;只要输入的密码正确&#xff0c;路由器就直接进入了用户模式。在该模式下&#xff0c;系统提示符为一个尖括号(>)。如果用户以前为路由器输入过名称&#xff0c;则该名称将会显示在尖指号的前…

目标检测——YOLOX算法解读

论文&#xff1a;YOLOX: Exceeding YOLO Series in 2021(2021.7.18) 作者&#xff1a;Zheng Ge, Songtao Liu, Feng Wang, Zeming Li, Jian Sun 链接&#xff1a;https://arxiv.org/abs/2107.08430 代码&#xff1a;https://github.com/Megvii-BaseDetection/YOLOX YOLO系列算法…

序列化与反序列化介绍

文章目录 一、序列化与反序列化二、PHP反序列化漏洞成因三、JAVA反序列化 一、序列化与反序列化 在PHP语言开发层面上基本都是围绕着serialize()&#xff0c;unserialize()这两个函数。serialize()函数序列化对象后&#xff0c;可以很方便的将它传递给其他需要它的地方&#x…

【数据结构和算法初阶(C语言)】二叉树的顺序结构--堆的实现/堆排序/topk问题详解---二叉树学习日记②12

目录 ​编辑 1.二叉树的顺序结构及实现 1.1 二叉树的顺序结构 2 堆的概念及结构 3 堆的实现 3.1堆的代码定义 3.2堆插入数据 3.3打印堆数据 3.4堆的数据的删除 3.5获取根部数据 3.6判断堆是否为空 3.7 堆的销毁 4.建堆以及堆排序 4.1堆排序---是一种选择排序 4.2升序建大堆&a…

LeetCode每日一题【206. 反转链表】

思路&#xff1a;双指针&#xff0c;一前一后&#xff0c;逐个把指向后面的指针指向前面。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), ne…

自动化的免下车服务——银行、餐厅、快餐店、杂货店

如果您在20世纪70年代和2020年分别驾车经过免下车服务餐厅&#xff08;汽车穿梭餐厅&#xff09;&#xff0c;您会发现&#xff0c;唯一的不同是排队的车型。50多年来&#xff0c;免下车技术一直为我们提供着良好的服务&#xff0c;但现在也该对它进行现代化改造了。 乘着AI和自…

mini2440 LCD(型号:P43)驱动的背光驱动失效原因分析

目录 概述 1 背光驱动移植 1.1 问题描述 1.2 LCD背光驱动 1.2.1 原理图分析 2 移植驱动程序 2.1 编写驱动代码 2.2.1 编写代码 2.2.2 添加驱动配置 2.2 配置驱动至内核 3 测试背光控制 4 分析P43屏的资料 4.1 查询P43的资料 4.2 关于P43的介绍 5 失效原因分析 概…

ZYNQ AXI GPIO

1 原理介绍 一个AXI GPIO 模块有两个GPIO&#xff0c;分别是GPIO和GPIO2&#xff0c;也就是channel1和channel2&#xff0c;为 双向IO。 AXI GPIO的寄存器也不多&#xff0c;主要是两个channel 的数据寄存器GPIO_DATA和GPIO2_DATA&#xff0c;两个channel的方向控制GPIO_TRI和…

Tempo Talents | 创新专业建设方案,赋能高校4+N大数据学科人才培养

数字经济成为国家战略&#xff0c;是新一轮的经济发展引擎&#xff0c;数字人才、复合型人才成为发展的关键和核心要素。各级政府、区域开始以区域产业为导向&#xff0c;培育、聚集产业所需的数智化人才。 高校作为人才培养的重要基地&#xff0c;也发挥着不可或缺的作用。他…