03-react基础知识-HOOK

news2024/12/25 20:53:07

一、useState

二、 useEffect

三、 useCallback

四、 useMemo 

五、 useContext

        含义:useContex用于在组件中获取上层组件通过 Context 提供的数据。它可以让你跨越组件树层级来访问共享的数据,避免了通过层层传递 props 的带来的问题。

1.实现数据的跨级传递(父组件的数据可以直接传递给孙组件或者孙孙组件)

2.组件本身可以充当数据的消费者和数据的提供者

3.若要在子组件中使用父组件的过程中,修改了子组件中的数据后,父组件中使用了该变量的地方都会刷新,则在使用provider和value进行传值时,可以以数组的形式进行传递,这样子组件即可正常使用set来修改数据了(同步更新)

<Sonctx.Provider value={[sonmsg, setsonmsg]}>
                <Grandson></Grandson>
            </Sonctx.Provider>
//app上下文对象==================================================
// 1-1:=======创建appctx文件并编辑下面语句
import React from "react";
// 创建一个上下文对象
let Appctx = React.createContext({})
// 导出appctx对象
export default Appctx


//子组件的上下文对象==========================================================
import React from "react";
// 创建一个上下文对象
let Sonctx = React.createContext({})
// 导出Sonctx对象
export default Sonctx

//孙组件上下文对象==========================================================
import React from "react";
// 创建一个上下文对象
let GrandsonCtx = React.createContext({})
// 导出GrandsonCtx对象
export default GrandsonCtx



//app组件中=============================================================
import React, { useState, useCallback } from 'react'
import Son from './component/hook/01-Son.jsx'
//1-2======== 引入自己创建的Appctx上下文对象
import Appctx from './component/hook/01-app.jsx'
function App() {
  // 定义一个appmsg数据
  let [appmsg, setmsg] = useState({ name: "jack", age: 23 })
  return (
    <div>
      <h5>app组件</h5>
      <div>{appmsg.name}</div>
      {/* 1-3=======:使用provider标签和value属性来传递 父组件的appmsg数据*/}
      <Appctx.Provider value={appmsg}>
        <Son></Son>
      </Appctx.Provider>


    </div>
  )

}
export default App


//son组件中===================================================================================



import React, { useContext, useState } from 'react'
import Grandson from './02-granSon.jsx'
//1-5======: 引入appctx上下文对象
import Appctx from './01-app.jsx'
// 2-1:引入Sonctx这个上下文对象,是自己创建的
import Sonctx from './01-Sonctx.jsx'
function Son() {
    // 1-6======:引入useContext这个函数,用useContext来接收从父组件传递过来的数据进行解构赋值
    let obj = useContext(Appctx)
    console.log("son组件的obj222", obj);

    //2-2: son组件可以是消费者,也可以作为别人的数据提供者:定义一个变量sonmsg
    const [sonmsg, setsonmsg] = useState({ name: "小将", age: 26, sex: "girl" })
    return (
        <div>
            <h5>son组件</h5>
            {/* 这里即可正常使用父组件传递过来的数据 */}
            <div>{obj.name}</div>
            <div>{obj.age}</div>
            <div>son组件的值==当孙组件进行修改了sge数据,这里是否会改变======{sonmsg.age}</div>
            {/* 使用provider标签和value属性进行传递 */}
            {/*2-3: son组件给grandson组件提供数据 */}
            {/* 这里将son的数据sonmsg和setsonmsg传递给了孙组件,即可实现在孙组件中修改子组件的值了 */}
            <Sonctx.Provider value={[sonmsg, setsonmsg]}>
                <Grandson></Grandson>
            </Sonctx.Provider>

        </div>
    )
}
export default Son



//孙组件中================================================================


import React, { useContext } from 'react'
import Appctx from './01-app'
// 2-4====引入Sonctx这个上下文对象
import Sonctx from './01-Sonctx'
function Grandson() {
    // 2-5===使用usecontext来接收从son组件中传递过来的数据进行解构赋值
    let [granobj, setsonmsg] = useContext(Sonctx)
    console.log("grandson的数据::孙组件", granobj, 1111, setsonmsg);

    // 父组件可以直接将其数据传递给孙组件乃至孙孙组件
    let Apobj = useContext(Appctx)
    console.log("app传递过来的数据", Apobj);


    let change = () => {
        // 这是主流的写法,19行为深拷贝的概念,这不是标准的写法
        granobj.age = "33"
        setsonmsg(JSON.parse(JSON.stringify(granobj)))
    }
    return (
        <div>
            <h5>Grandson组件</h5>
            {/* 2-6===即可将其看作变量正常使用 */}
            <div>{granobj.name}</div>
            <div>{granobj.age}</div>
            <div>{granobj.sex}</div>

            <button onClick={change}>孙按钮</button>
        </div>
    )
}
export default Grandson


六、useReduce 

含义:和useState类似,都是用来管理组件状态的,只是useReducer返回的dispatch函数是用来改变state的action值得,而不是直接设置state的值,不同的action如何产生新的state的值是在reducer函数里面定义的。

        格式:const [state,dispatch]=usereducer(reducer,initialArg,init?)

state:当前的变量

dispatch:用于修改state的函数,类似于usestate中的set函数

reducer:一个函数,格式为:let reducer=(currentState,action)=>newState,该函数会接收当前的state和当前的dispatch中的action为参数,然后返回一个state,也就是说,reducer函数负责状态转换的工作。(可以决定如何修改state这个变量

通过当前的状态(state)和动作(action)返回修改后的新的状态的值,接收两个参数:状态值(state)和状态值(action

initialArg:state的初始值

init:把第二个参数传给了第三个函数,让这个函数处理一下,处理的结果作为初始值传递给state

import React, { useReducer } from 'react'

function App() {
  let [count, setcount] = useReducer((currentstate, action) => {
    console.log(currentstate, action);
    // count的值是return返回的值,返回为20的话,点击按钮,页面的变量为20咯,再一次点击:当前的值也就是return返回的值20,页面也就不会再刷新了
    return 20
    // 返回为action的话,传递的是最新的值,点击按钮,页面便是修改后的值:1,6,11。。。。。。。。
    // return action
    //若有第三个参数存在的话就是将第二个参数处理一下,然后将处理过的数据给state作为初始值:这里是将1交给第三个参数将其加100后给count。最后页面一加载,页面显示的是101
  }, 1, (arg) => { return arg + 100 })
  let change = () => {
    setcount(count + 5)
  }
  return (
    <div>
      <h5>app组件</h5>
      <div>{count}</div>
      <button onClick={change}>{count}</button>
    </div>
  )

}
export default App

进阶版

若该变量里面的数据比较多,对其进行修改和传递的写法

问:1.switch里面的case语句都是相似的,但为什么不直接使用下面这个写法呢

                

        上面的写法是处理好了再将处理好了再传递过去修改

下面的写法:在case里面可以写业务逻辑的,可以自己决定如何处理该数据,也就是统一来配置修改仓库的逻辑

case语句里面的修改是统一修改的逻辑代码。

2.case语句里的为什么要大写呢?

答:为了和普通的数据进行区分,不是数据,是取数据和保存数据的一个判断。

import React, { useReducer } from 'react'

function App() {
  // 1.1====让count的初始值为obj这个对象
  let obj = { name: "cup杯子", price: "14", comment: "非常好呀,下次还来" }
  // 1.2解构赋值====这里的dispatch相当于usestate的set函数
  let [count, dispatch] = useReducer(reducer, obj)

  // 1.3=========定义reducer函数:currentstate:为当前的那个状态,action传进来的最新的那个
  let reducer = (currentstate, action) => {
    console.log("当前的那个状态:", currentstate, "传进来的那个状态:", action);
    // 1.5==== 用switch进行判断,匹配是否匹配
    switch (action.type) {
      case "NAME":
        // 1.6===将新值传递给旧值:currentstate为旧值,action为新值
        currentstate.name = action.value
        break;
      case "PRICE":
        currentstate.price = action.value
        break;
      case "COMMENT":
        currentstate.comment = action.value
        break;
    }
    //1.7===== currentstate确实被修改了,但它本身是一个引用数据,属性值改变了,但属性没改,返回的还是引用数据所以页面不会刷新,需要用到深拷贝的知识点

    return JSON.parse(JSON.stringify(currentstate))
  }


  // 1.4====:通过dispatch中的type和value来实现数据修改
  let change = () => {
    dispatch({ type: "PRICE", value: "20" })
  }
  return (
    <div>
      <h5>app组件</h5>
      <div>{count.name}</div>
      <div>{count.price}</div>
      <button onClick={change}>{count.price + 10}</button>

    </div>
  )

}
export default App

进阶版,将reducer函数封装到一个文件中,直接引进来使用。

将reducer封装到一个文件中,引入使用=========================================================
import { useReducer } from "react";
function usestore() {
    // 1.1====让count的初始值为obj这个对象
    let obj = { name: "cup杯子", price: "14", comment: "非常好呀,下次还来" }

    // 1.3=========定义reducer函数:currentstate:为当前的那个状态,action传进来的最新的那个
    let reducer = (currentstate, action) => {
        console.log("当前的那个状态:", currentstate, "传进来的那个状态:", action);
        // 1.5==== 用switch进行判断,匹配是否匹配
        switch (action.type) {
            case "NAME":
                // 1.6===将新值传递给旧值:currentstate为旧值,action为新值
                currentstate.name = action.value
                break;
            case "PRICE":
                currentstate.price = action.value
                break;
            case "COMMENT":
                currentstate.comment = action.value
                break;
        }
        //1.7===== currentstate确实被修改了,但它本身是一个引用数据,属性值改变了,但属性没改,返回的还是引用数据所以页面不会刷新,需要用到深拷贝的知识点

        return JSON.parse(JSON.stringify(currentstate))
    }
    // 解构赋值:将store的初始值赋值为obj这个对象
    let [store, dispatch] = useReducer(reducer, obj)
    return [store, dispatch]
}
// 导出的是自己自定义的hook
export default usestore

app组件中===================================================

import React, { useReducer } from 'react'
import Son from './component/01-son.jsx'
// 引入自己定义的storehook
import usestore from './store.jsx'
function App() {
  // 使用自定义的
  let [store, dispatch] = usestore()
  console.log(store);
  // 使用action将name的值改为海绵宝宝好杯子
  let action = { type: "NAME", value: "海绵宝宝好杯子" }
  // 点击按钮,则调用dispatch函数,
  let change = () => {
    dispatch(action)
  }

  // 现在存在一个问:app组件和son组件中都有name属性,在son组件中点击按钮将name的值改变了,son页面的值改变了,但app组件没有改变
  // 因为引进来的是一个函数,每一次调用的都是独立的结果,各各自是各自的。

  return (
    <div>
      <h5>app组件</h5>
      <div>{store.name}</div>
      <div>{store.price}</div>
      <Son></Son>
    </div>
  )

}
export default App


//son组件中===========================================================================

import React, { useReducer } from 'react'
// 引入自己定义的storehook
import usestore from '../store.jsx'
function Son() {

    let [store, dispatch] = usestore()
    console.log(store);
    // 使用action将name的值改为海绵宝宝好杯子
    let action = { type: "NAME", value: "海绵宝宝好杯子" }
    // 点击按钮,则调用dispatch函数,
    let change = () => {
        dispatch(action)
    }
    return (
        <div>
            <h5>son组件</h5>
            <div>{store.name}</div>
            <button onClick={change}>{store.name}</button>
        </div>
    )

}
export default Son


 问题:app组件和son组件中都有name属性,在son组件中点击按钮将name的值改变了,son页面的值改变了,但app组件没有改变。
          因为引进来的是一个函数,每一次调用的都是独立的结果,各各自是各自的。

所以要利用usecontext、插槽、usereducer来实现仓库

在main.jsx文件中引入刚刚封装的store

七、useRef 

八、自定义Hoook

含义:将官方的hooks搭配使用设计出自己的use开头的函数,该函数具备自定义的功能,就是自定义hook。

九、高阶组件

含义:函数调用后返回了一个组件,这个函数就是高阶组件

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

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

相关文章

【Redis】Redis与SSM整合Redis注解式缓存Redis解决缓存问题

一&#xff0c;Redis与ssm整合 1.1 pom.xml配置 在pom.xml中配置相关的redis文件 redis文件&#xff1a; <redis.version>2.9.0</redis.version> <redis.spring.version>1.7.1.RELEASE</redis.spring.version><dependency><groupId>red…

【排版教程】使用Latex ACM 双栏会议模板如何添加跨栏的图片

0 前言 模板中默认的图片插入的写法是下图这样的单栏图片&#xff0c;但是一般我们自己绘制的系统整体结构框图都是比较长的&#xff08;横向长度&#xff09; 我们想插入一个类似于这样的长图片 但是模板中给的这个例子&#xff0c;是插入的一个pdf文件。在实际使用中&…

2023年【金属非金属矿山(地下矿山)安全管理人员】实操考试视频及金属非金属矿山(地下矿山)安全管理人员操作证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员实操考试视频考前必练&#xff01;安全生产模拟考试一点通每个月更新金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员操作证考试题目及答案…

传输线在阻抗匹配时串联端接电阻为什么要靠近发送端

在进行阻抗匹配的时候我们可以在电阻源端放置一个串联端接电阻&#xff0c;但是有时候受到空间的限制可能会把电阻摆的稍微远一点&#xff0c;那么这个时候大家可能会有疑问&#xff0c;电阻离发送端远一点或者电阻放置在接收端&#xff0c;那么电阻还能消除传输线的反射吗&…

uniApp封装请求

一、request封装 创建一个api文件夹&#xff0c;用于存放所有的API接口文件。在api文件夹中创建一个request.js文件&#xff0c;用于配置接口的路由信息、请求地址和请求方法等信息。示例代码如下&#xff1a; const BASE_URL http://example.com/api // 替换为你的接口基础U…

小白学爬虫:通过关键词搜索1688商品列表数据接口|1688商品列表数据接口|1688商品列表数据采集|1688API接口

通过关键词搜索1688商品列表数据接口可以使用1688开放平台提供的API接口实现。以下是使用关键词搜索商品列表数据的基本步骤&#xff1a; 1、注册并获取AppKey。 2、构造请求参数&#xff0c;包括搜索关键词、页码、每页条数等。 3、通过API接口链接&#xff0c;将请求参数发送…

第四章《全景图:机器学习路线图》笔记

4.1 通俗讲解机器学习是什么 4.1.1 究竟什么是机器学习 卡内基梅隆大学机器学习领域的著名学者汤姆米切尔曾经在 1997 年对机器学习做出过更为严谨和经典的定义: A program can be said to learn from experience E with respect to some class of tasks T and performance …

发票识别神器:自动化读取纸质发票信息,提高工作效率

当今数字化时代&#xff0c;纸质发票的处理和管理成为许多企业和个人面临的挑战。手动处理大量纸质发票不仅费时费力&#xff0c;还容易导致错误和遗漏。因此&#xff0c;自动识别纸质发票上的信息的软件成为一个备受关注的话题。 幸运的是&#xff0c;现在有一款先进的软件能…

[C/C++]数据结构 链表OJ题 : 链表中倒数第k个结点

描述 输入一个链表&#xff0c;输出该链表中倒数第k个结点。 方法一: 暴力求解 先遍历一遍整个链表获取链表长度len,则倒数第k个结点就是整数第len-k个结点 struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {struct ListNode* cur pListHead;int len …

RK3568驱动指南|第七篇 设备树-第61章 实例分析:pinctrl

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

宝马——使用人工智能制造和驾驶汽车

德国汽车制造商宝马(BMW)每年在全球制造和销售250万台汽车&#xff0c;其品牌包括宝马、MINI和劳斯莱斯。 宝马汽车以其卓越的性能和对新技术的应用而著名&#xff0c;它是道路上最精致的汽车之一&#xff0c;并且和其竞争对手戴姆勒(Daimler)一样&#xff0c;在将自动驾驶汽车…

最新、最全、最详细的 K8S 学习笔记总结

Kubernetes就是一个编排容器的工具&#xff0c;一个可以管理应用全生命周期的工具&#xff0c;从创建应用&#xff0c;应用的部署&#xff0c;应用提供服务&#xff0c;扩容缩容应用&#xff0c;应用更新&#xff0c;都非常的方便&#xff0c;而且可以做到故障自愈。 K8S的前景…

APP 备案公钥、签名 MD5、SHA-1、SHA-256获取方法

​ 公钥和 MD5 值可以通过苹果开发工具、Keytool、appuploder 等多种工具获取&#xff0c;最简单的就是以 appuploader为例。 1.下载 appuploader工具 &#xff0c;点击此处 下载 appuploader 工具。 ​2.下载完成后&#xff0c;解压压缩包&#xff0c;双击 appuploder 运行。…

CRM软件对B2B销售的作用有哪些?

​ CRM软件对B2B销售有用吗&#xff1f;面向B端企业的B2B销售模式&#xff0c;是一个比B2C模式错综复杂的业务形态。最初CRM软件就是为这种业a务模式设计的&#xff0c;十几年来碰撞出来的火花不一而足。 B2B&#xff08;也叫BtoB&#xff09;销售的特点几乎等同于难点&#x…

SS928开发板 开发记录三: nfs 挂载

1.创建nfs文件 1.安装nfs sudo apt-get install nfs-kernel-server 2.创建文件 sudo mkdir /home/nfsroot 3.给权限 sudo chmod 777 nfsroot 4.设置 vim /etc/exports 最后一行加入 /nfsroot *(rw,sync,no_root_squash)5. 重启nfs sudo service nfs-kernel-server r…

小白学爬虫:手机app分享商品短连接获取淘宝商品链接接口|淘宝淘口令接口|淘宝真实商品链接接口|淘宝商品详情接口

通过手机APP分享的商品短链接&#xff0c;我们可以调用相应的接口来获取淘口令真实URL&#xff0c;进而获取到PC端的商品链接及商品ID。具体步骤如下&#xff1a; 1、通过手机APP分享至PC端的短链接&#xff0c;调用“item_password”接口。 2、该接口将返回淘口令真实URL。 3…

macOS电池续航工具:Endurance中文

Endurance for Mac是一款强大而实用的电池管理和优化软件&#xff0c;专为MacBook设计。通过智能调整系统设置和管理后台应用&#xff0c;它能有效延长电池续航时间&#xff0c;提升工作和娱乐效率&#xff0c;成为你在各种场合下的得力助手。 Endurance for Mac软件的功能特色…

Perl使用爬虫ip服务器采集图书网站信息

这是一个使用 Perl 和爬虫ip服务器来爬取图书网站信息采集的示例代码。以下每行代码的中文解释&#xff1a; use LWP::UserAgent; use HTTP::Proxy; use HTML::TreeBuilder;# 创建爬虫ip服务器 my $proxy HTTP::Proxy->new(host > "www.duoip.cn",port > 8…

AI:65-基于机器学习预测股市行情

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

CNVD-2023-08743:宏景HCM SQL注入漏洞复现 [附POC]

文章目录 宏景HCM SQL注入漏洞复现 (CNVD-2023-08743) [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 宏景HCM SQL注入漏洞复现 (CNVD-2023-08743) [附POC] 0x01 前言 免责声明&#xff1a;请勿利用文章…