ReactHooks(一)

一.使用规则

  • hook和生命周期函数一样,必须写在函数最顶层;
  • 而且hook不应该被嵌套进条件或者循环语句中;
  • hook只能在函数组件或者自定义hook中被使用,而不能用于普通函数或者class组件中。

二.useState:使用状态(只在初始化时调用一次)

2.1 赋初值方法

  • 直接赋值
    基本语法: const [count,setCount]=usestate(0)
    count:当前状态值 setcount允许你更新状态的函数。
    1、 当状态发生变化时,函数组件重新渲染一次。
    2、当函数式组件被重复执行时,不会重复调用 useState()给数据赋初始值,而是复用上次的 state 的值。

  • 利用函数的返回值赋值
    基本语法: const [count,setCount]=usestate(()=>初始值)

2.usestate()函数有一个参数,参数可以是任意值,用来进行数据的定义。并且返回一个数组,数组中有两个对象,第一个是state变量并且把参数值赋予它,第二个是设置state变量值得方法。
注意:
1、 我们可以通过次函数定义多个state数据,但我们应保证每一个state数据都具有意义。同种意义范围的state数据应该放在同一个state中。​​​​​​​
2、setXXX调用方式

  • setXXX(新值)
  • 解决数值更新不急时: setXXX(fn) / setXXX((prev)=>基于 prev 计算并 return 一个新值)

2.2 更新对象类型的值

setUser({…user})
setUser(Object.assign({},user))

2.3 使用 setState 模拟组件强制刷新

import React,{useState} from 'react'
// 强制刷新
const ForceUpdate:React.FC = () =>{
const [,forceUpdate] =  useState({})
const onFresh = () =>{forceUpdate({})
}return <><button onClick={onFresh}> 强制刷新————{Date.now()}</button></>
}
export default ForceUpdate

三.useEffect:增加了在功能组件执行副作用的功能。

3.1 函数的副作用

函数除了返回值外,对外界环境造成的其他影响。即与组件渲染无关的操作。如:获取数据、修改全局变量、更新 DOM

3.2 参数

相当于组件中编写了componentDidMount钩子函数。
useEffect()函数每次渲染都会执行,useEffect是非阻塞的,所以是异步代码。
useEffect()有两个参数:
①第一个是副作用函数,用来编写可能具有副作用的代码,副作用函数可以返回一个函数对象,这个函数对象用来清除副作用,不用清除,则不用返回;
②第二个参数是数组(可选),里面传入副作用中使用到的数据变量,并且这个变量得具有变化的特性,这个参数主要用于优化,反之进行重复渲染。

3.3 执行时机

  • 如果没有指定依赖项数组,则会在函数组件每次渲染完成后执行。
  • useEffect 会在组件首次渲染完毕,默认执行一次。
  • 组件每次渲染完毕,会触发 useEffect 中的回调函数,如果给了依赖想项数组,则还要判断依赖项是否变化,再决定是否触发回调
    注意:
  • 不要在 useEffect 中改变依赖项的值,会造成死循环。
  • 多个不用功能的副作用尽量分开声明,不要写到一个 useEfffect 中。

3.4 如何清理副作用

1、基本语法

// react帮我们调用清理函数  当执行useEffect时,先去判断有无清理函数,若有则先执行清理函数。
useEffect(()=>{return ()=>{/* 在这里执行自己的清理操作*/}
},[依赖项])

2、执行时机:

  • 当 effect 副作用函数执行之前,会先执行清理函数

  • 卸载组件时候执行
    2、应用场景

  • 清除定时器 / 网络请求

import React, { useState, useEffect } from "react";
const ChildColor = () => {const [color, setColor] = useState(0);useEffect(() => {const controller = new AbortController();// { signal: controller.signal }   controller.signal:终止信号 需要和fetch进行绑定fetch("https://api.liulongbin.top/v1/color", { signal: controller.signal }).then((res) => res.json()).then((resp) => {console.log(resp, "resp");setColor(resp.data.color);}).catch((err) => {console.log(err.message, "err");});// return 一个清理函数 终止请求:当隐藏组件时候// controller.abort()终止请求return () => controller.abort();}, []);return (<div><h1>颜色值:{color}</h1></div>);
};
export const FatherColor: React.FC = () => {const [flag, setFlag] = useState(true);return (<div><h3>父组件</h3><buttononClick={() => {setFlag((prev) => !prev);}}>Toggle</button><hr /><h3>子组件</h3>{flag && <ChildColor />}</div>);
};
  • 解绑事件监听

四.useRef:用来保存对象

1、使用方法:const refObj = useRef(初始值)
2、解决两个问题

  • 获取 DOM 元素 或子组件的实例对象
import React,{useRef} from 'react'
//点击按钮获取input元素  并贴是的input获取焦点
const inputRef:React.FC = () =>{
// 添加范型定义 有了类型定义,则会自动提示
const iptRef=  useRef<HTMLInputElement>(null)
const getFocus = () =>{iptRef.current?.focus()
}return <><input type="text" ref={iptRef}/><button onClick={getFocus}> 获取焦点</button></>
}
export default inputRef
  • 存储渲染周期之间共享的数据
import React, { useRef, useState } from "react";
// 方法一:全局定义的preCount 可能会造成变量全局污染
let preCount:number;
const LifeCycle: React.FC = () => {const [count, setCount] = useState(0);const add = () => {setCount((state) => state + 1);preCount = count;};return (<><h1>新值是:{count} 旧值是:{preCount}</h1><button onClick={add}> +1</button></>);
};
export default LifeCycle;// 方法二:全局定义的preCount 可能会造成变量全局污染
const LifeCycle: React.FC = () => {const [count, setCount] = useState(0);const preRef =  useRef<number>()const add = () => {setCount((state) => state + 1);preRef.current = count;};return (<><h1>新值是:{count} 旧值是:{preRef.current}</h1><button onClick={add}> +1</button></>);
};
export default LifeCycle;

注意:

  • useRef()只在组件首次渲染的时候被创建
  • 如果组件是 rerender 的时候,不会重复创建 ref 对象
  • ref.current 变化时不会造成组件的 rerender
  • ref.current 不能作为其他 Hooks 的依赖项

五.forwardRef

5.1 解决父组件中不能直接引用子组件的 ref。

import React,{ useRef } from "react";
const Child: React.FC = () => {return <div>Child</div>;
};
export const Father: React.FC = () => {const childRef = useRef()return (<div>Father{/* 父组件中不能直接引用子组件的 ref。 */}<Child ref={childRef}/></div>);
};
import React, { useRef, useState, useImperativeHandle } from "react";
// const Child: React.FC = () => {
//   return <div>Child</div>;
// };
// 使用这个 React.forwardRef() 进行包裹子组件 并且类型声明去掉React.FC
// React.forwardRef() 第一个参数是props,第二个参数是 ref[这里的ref是父组件传过来的ref]
const Child = React.forwardRef((_, ref) => { // props没有使用,则用_占位const [count, setCount] = useState(0);const add = (step: number) => {setCount((state) => (state += step));};// useImperativeHandle 中的对象才是父组件的获取到的 refuseImperativeHandle(ref, () => ({name: "nihao ",}));return (<div><h1>count的值:{count}</h1><buttononClick={() => {add(1);}}>+1</button><buttononClick={() => {add(-1);}}>-1</button></div>);
});
export const Father: React.FC = () => {const childRef = useRef();const showRef = () => {console.log(childRef.current, "childRef");};return (<div><h3>父组件</h3><button onClick={showRef}>获取子组件的 Ref</button><hr /><h3>子组件</h3><Child ref={childRef} /></div>);
};

5.2 基于 useImperativeHandle 按需向外暴露成员

import React, { useRef, useState, useImperativeHandle } from "react";
const Child = React.forwardRef((_, ref) => {const [count, setCount] = useState(0);const add = (step: number) => {setCount((state) => (state += step));};// 基于 useImperativeHandle 按需向外暴露成员useImperativeHandle(ref, () => ({count,setCount,}));return (<div><h1>count的值:{count}</h1><buttononClick={() => {add(1);}}>+1</button><buttononClick={() => {add(-1);}}>-1</button></div>);
});
export const Father: React.FC = () => {const childRef = useRef<{count:number;setCount:(value:number)=>void}>();const reset = ()=>{childRef.current?.setCount(0)}return (<div><h3>父组件</h3><button onClick={reset}>重置子组件的count</button><hr /><h3>子组件</h3><Child ref={childRef} /></div>);
};

5.3 控制成员暴露的粒度

import React, { useRef, useState, useImperativeHandle } from "react";
const Child = React.forwardRef((_, ref) => {// props没有使用,则用_占位const [count, setCount] = useState(0);const add = (step: number) => {setCount((state) => (state += step));};useImperativeHandle(ref, () => ({count,// setCount,// 为了安全 减少成员暴漏粒度reset: () => {setCount(0);},}));return (<div><h1>count的值:{count}</h1><buttononClick={() => {add(1);}}>+1</button><buttononClick={() => {add(-1);}}>-1</button></div>);
});
export const Father: React.FC = () => {const childRef = useRef<{count:number;reset:()=>void}>();const reset = ()=>{childRef.current?.reset()}return (<div><h3>父组件</h3>{/* 通过useImperativeHandle 重置子组件的count */}<button onClick={reset}>重置子组件的count</button><hr /><h3>子组件</h3></div>);
};

5.4 useImperativeHandle 的第三个参数

  //useImperativeHandle的第三个参数// 如果不传,则只要有useState定义的值发生变化,则这个回调函数就会执行。性能不友好useImperativeHandle(ref, () => {console.log("执行了 useImperativeHandle");return {count,reset: () => {setCount(0);},};});// 如果只传一个空数组,在组件第一次渲染的时候执行useImperativeHandle(ref,() => ({count,reset: () => {setCount(0);},}),[]);// 如果回调函数返回的seate依赖变量,则只要该变量发生变化,则回调函数执行一遍useImperativeHandle(ref,() => ({count,reset: () => {setCount(0);},}),[count]);

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

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

相关文章

Java 面试相关问题(下)——JVM相关问题GC相关问题

1. 类加载1.1 类的生命周期说一下&#xff1f;1.2 介绍下生命周期中的加载&#xff1f;1.3 介绍下生命周期中的验证&#xff1f;1.4 介绍下生命周期中的准备&#xff1f;1.5 介绍下生命周期中的解析&#xff1f;1.6 介绍下生命周期中的初始化&#xff1f;1.7 介绍下生命周期中的…

科研绘图系列:R语言组合堆积图(stacked barplot with multiple groups)

介绍 通常堆积图的X轴表示样本,样本可能会存在较多的分组信息,通过组合堆积图和样本标签分组信息,我们可以得到一张能展示更多信息的可发表图形。 加载R包 knitr::opts_chunk$set(warning = F, message = F) library(tidyverse) library(cowplot) library(patchwork)导入…

KubeSphere安装时候报22端口连接不上的错误

使用KubeKey在Linux机器上以单节点模式安装KubeSphere和Kubernetes/K3时候报错误&#xff1a; error: Pipeline[CreateClusterPipeline] execute failed: Module[GreetingsModule] exec failed: failed: [LAPTOP-R028MMAA] failed to connect to 172.26.246.173: could not es…

富芮坤FR800X系列之按键检测模块设计

FR800X系列按键检测模块 读者对象&#xff1a; 本文档主要适用以下工程师&#xff1a; 嵌入式系统工程师 单片机软件工程师 IOT固件工程师 BLE固件工程师 文章目录 1.概要2.用户如何设计按键检测模块2.1 GPIO初始化2.2按键模块初始化2.3设计中断函数&#xff1a;2.4循环…

Spring循环依赖详解

一、什么是循环依赖 在Spring框架中&#xff0c;循环依赖是指两个或更多的Bean相互间直接或间接地依赖对方的情况。这种依赖关系可能导致Bean的实例化过程中出现问题&#xff0c;但Spring通过其内部的处理机制能够解决某些类型的循环依赖。 简单的说就是A依赖B&#xff0c;B依赖…

数据库安全综合治理方案(可编辑54页PPT)

引言&#xff1a;数据库安全综合治理方案是一个系统性的工作&#xff0c;需要从多个方面入手&#xff0c;综合运用各种技术和管理手段&#xff0c;确保数据库系统的安全稳定运行。 方案介绍&#xff1a; 数据库安全综合治理方案是一个综合性的策略&#xff0c;旨在确保数据库系…

Property ‘$router‘ does not exist on type TS2339

问题&#xff1a;Property XXX does not exist on type .... 启动VUE项目的时候&#xff0c;VUE文件没有报错&#xff0c;但是npm run serve之后&#xff0c;项目报错。 参考网上的写法, 用this[router] 可以解决此问题&#xff0c;没尝试过。 但是项目里太多地方使用this.写…

photoshop学习笔记——选区3 选区的变化

选区制作完成之后可以对选区进行变化 主要有&#xff1a; 反选&#xff1a;shift ctrl I 变换 修改&#xff1a; 边界 设置选区的边界大小 类似 CSS中的borderSize平滑 对选区的角进行平滑扩展 向外扩展选区收缩 向内收缩选区羽化 让边界变得过渡透明度 设置…

Python中最好学和最实用的有哪些库和框架

Python拥有丰富的库和框架&#xff0c;这些库和框架覆盖了从数据处理、科学计算、Web开发到机器学习等多个领域。以下是一些值得学习的Python库和框架&#xff1a; 数据处理与科学计算 NumPy 描述&#xff1a;NumPy是Python中用于科学计算的一个库&#xff0c;它提供了一个强…

ubuntu新机依赖

换源加ros wget http://fishros.com/install -O fishros && . fishros 单击最小化 gsettings set org.gnome.shell.extensions.dash-to-dock click-action minimize tbb Ubuntu 安装 tbb 步骤详解_ubuntu tbb-CSDN博客 //#include <opencv/cv.h> #include…

MySQL的面试题,从简单到困难三道题目

1. 简单题&#xff1a;请简述MySQL是什么&#xff0c;并说明其默认端口号。 参考答案&#xff1a; MySQL简介&#xff1a;MySQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于Web开发中&#xff0c;用于存储、查询、更新和管理数据。…

MySQL作业四

1. 创建数据库mydb15_indexstu 2. 创建表student&#xff0c;course&#xff0c;sc 2.1 创建表student 2.2 创建表course 2.3 创建表sc 3. 处理表 3.1 修改表student中年龄&#xff08;sage&#xff09;字段属性&#xff0c;数据类型由int改变为smallint 3.2 为表course中cno…

WEB渗透Web突破篇-SQL注入(MYSQL)

注释符 # -- 注意这里有个空格 /* hello */ /*! hello */ /*!32302 10*/ MYSQL version 3.23.02联合查询 得到列数 order by或group by 不断增加数字&#xff0c;直到得到报错响应 1 ORDER BY 1-- #True 1 ORDER BY 2-- #True 1 ORDER BY 3-- #True 1 ORDER BY 4-- #Fal…

Ubuntu 22.04 上安装 Java8 或者java 11

在 Ubuntu 22.04 上安装 Java 8 环境可以通过以下步骤完成。请注意&#xff0c;Java 8 已经到达了维护期末&#xff0c;建议升级到更新的 Java 版本以获得更好的安全性和性能。 java 8 方法一&#xff1a;使用 OpenJDK 8 更新包管理器&#xff1a; 在终端中执行以下命令以更新…

【数据结构】栈(基于数组、链表实现 + GIF图解 + 原码)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;数据结构 &#x1f4da;本系列文章为个人学…

Golang | Leetcode Golang题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; func missingNumber(nums []int) int {n : len(nums)total : n * (n 1) / 2arrSum : 0for _, num : range nums {arrSum num}return total - arrSum }

scrapy爬取城市天气数据

scrapy爬取城市天气数据 一、创建scrapy项目二、修改settings,设置UA,开启管道三、编写爬虫文件四、编写items.py五、在weather.py中导入WeatherSpiderItem类六、管道中存入数据,保存至csv文件七、完整代码一、创建scrapy项目 先来看一下爬取的字段情况: 本次爬取城市天…

【中项】系统集成项目管理工程师-第5章 软件工程-5.3软件设计

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

密码暴力破解漏洞2024.7.26

python暴破 1、从字典读取值&#xff0c;生成密码 2、HTTP连接到需要暴破的地址 3、获得HTTP响应&#xff0c;分析响应结果&#xff0c;看看有没有错误提示 “Username and/or password incorrect.” 4、如果有提示&#xff0c;就继续下一次循环 5、如果没有&#xff0c;就…

一文解决 | Linux(Ubuntn)系统安装 | 硬盘挂载 | 用户创建 | 生信分析配置

原文链接&#xff1a;一文解决 | Linux&#xff08;Ubuntn&#xff09;系统安装 | 硬盘挂载 | 用户创建 | 生信分析配置 本期教程 获得本期教程文本文档&#xff0c;在后台回复&#xff1a;20240724。请大家看清楚回复关键词&#xff0c;每天都有很多人回复错误关键词&#xf…