开发中常用的Hook
开发中常用的Hook
什么是Hook?
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数,用来实现一些 class 组件的特性的。
1 // 引入 React 中的 useState Hook。它让我们在函数组件中存储内部 state。
2 import React, { useState } from 'react';
3
4 function Example() {
5 // 声明一个叫 “count” 的 state 变量。
6 //useState 就是一个 Hook
7 //当前状态和一个让你更新它的函数
8 //useState( ) 括号里面是count 的初始值
9 const [count, setCount] = useState(0);
10 return (
11 <div>
12 <p>You clicked {count} times</p>
13 <button onClick={() => setCount(count + 1)}>
14 Click me
15 </button>
16 </div>
17 );
18 }
Hook 不能在 class 组件中使用
class 组件比较重量级 -- 开发和维护有一定的难度,后来使用 函数组件,比较轻量,但是没有 calss的特性(state),需要使用一些别的方式来弥补 --> Hooks
EffectHook(副作用Hook)
副作用 hook 用来处理一些React之外的事件,比如ajax请求
但是其实 EffectHook 最常见的使用场景是 模拟 生命周期
用法:当useEffect依赖的数据发生变化,就会调用回调函数
useEffect(回调函数, [依赖的数据]);
格式 :
useEffect(当依赖发生变化时调用的函数, [依赖的数据]);
1 //需求:监视count
2 //引入副作用钩子函数
3 import React, { useEffect } from "react";
4
5 export default function EffectHook() {
6
7 const [count, setCount] = useState(0);
8
9 //count作为EffectHook的依赖,所以只要count发生了变化,就会触发这个回调的调用。
10 useEffect(() => {
11 console.log("EffectHook调用了");
12 },[count]);
13
14 const onClick = () => {
15 setCount(count + 1);
16 };
17
18 return (
19 <div>
20 <p>Count:{count}</p>
21 <p>Double:{double}</p>
22 <button onClick={onClick}>++</button>
23 </div>
24 );
25 }
使用EffectHook模拟生命周期:
a.模拟componentDidMount
useEffect(() => {
console.log("这是用来模拟挂载期的");
}, []);
b.模拟componentDidUpdate
useEffect(() => {
console.log("这是用来模拟更新期的");
}, [deps]);
c.模拟componentWillUnmount
useEffect(() => {
return ()=>{
// 在这里面写卸载期的代码
console.log("这是用来模拟卸载期的");
}
}, []);
注意:
同个useEffect下,在检测销毁和检测字段更新之间,只能二选一。留下空数组,可以检测到return中的销毁。数组非空时,视图更新会带动return返回值,因此如果要检测字段更新,就无法检测销毁。
StateHook
这是一个react提供好的用于实现state响应式特性的hook,使用如下:
1 export default function StateHook() {
2 // 调用useState得到一个数组,顺便解构出来两个东西,一个是数据,一个是用于操作数据的函数
3 const [count, setCount] = useState(0);
4 const onClick = () => {
5 // 调用对应的方法操作数据
6 setCount(count + 1);
7 };
8 return (
9 <div>
10 {/* 直接渲染对应的数据 */}
11 <p>Count:{count}</p>
12 <button onClick={onClick}>增加</button>
13 </div>
14 );
15 }
值得注意的是,hook只能使用在函数的最外层,任何别的位置都会报错。
声明多个 state 变量
你可以在一个组件中多次使用 State Hook
1 function ExampleWithManyStates() {
2 // 声明多个 state 变量!
3 const [age, setAge] = useState(42);
4 const [fruit, setFruit] = useState('banana');
5 const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
6 // ...
7 }
自定义Hook
使用hook可以让我们的数据的操作数据的逻辑放在一起,并且可以实现封装,把代码整理地更加易于维护。
如果在操作数据的过程中有一些比较复杂的逻辑,我们就可以采用自定义hook的方式把这部分逻辑分离出来。
1 export default function StateHook() {
2 const [count, setCount] = useState(0);
3 const onClick = () => {
4 // 如果有更加复杂的逻辑(假装很复杂)
5 let val = 0;
6 if (count > 0) {
7 val = count - 1;
8 } else {
9 val = count + Math.floor(Math.random() * 10);
10 }
11 setCount(val);
12 };
13 return (
14 <div>
15 <p>Count:{count}</p>
16 <button onClick={onClick}>增加</button>
17 </div>
18 );
19 }
如果我们在页面里面有大量的复杂逻辑,这样同样会使代码变得非常杂乱,后期难以维护,于是我们可以这样写。
1 // 自定义hook要求以use开头
2 function useCount(initValue = 0) {
3 const [count, setCount] = useState(initValue);
4 const fn = () => {
5 let val = 0;
6 if (count > 0) {
7 val = count - 1;
8 } else {
9 val = count + Math.floor(Math.random() * 10);
10 }
11 setCount(val);
12 };
13 return [count, fn];
14 }
15 export default function StateHook() {
16 // 调用我们自定义的hook , 把复杂的逻辑全抽离到自定义hook,这样在我们的组件里面就尽可能简洁了
17 const [count, setCount] = useCount();
18 const onClick = () => {
19 setCount();
20 };
21 return (
22 <div>
23 <p>Count:{count}</p>
24 <button onClick={onClick}>增加</button>
25 </div>
26 );
27 }
ContextHook
使用 useContext 使用context 进行多级组件传递数据
用法:
createContext
Provider
useContext
const Provider给的value = useContext(在第1步创建的context);
ContextHook基本使用步骤如下:
a.调用createContext创建一个Context对象
const MyContext = createContext();
b.使用Provider组件提供一个“全局”数据
1 export default function ContextHook() {
2 const [count, setCount] = useState(10);
3 const add = (val) => {
4 setCount(count + val);
5 };
6 return (
7 <MyContext.Provider value={{ count, add }}>
8 <Parent />
9 </MyContext.Provider>
10 );
11 }
c.在后代组件里面使用useContext方法获取Context对象
1 function Parent() {
2 return (
3 <div>
4 <Child />
5 </div>
6 );
7 }
8 function Child() {
9 const context = useContext(MyContext);
10 return (
11 <div>
12 {/* context对象就是之前的Provider里面的value属性 */}
13 <p>count from ancestors:{context.count}</p>
14 <button onClick={() => context.add(1)}>Add</button>
15 </div>
16 );
17 }
18 import React, { createContext, useContext, useState } from "react";
19 // 1. 创建一个context
20 const MyContext = createContext();
21
22 export default function ContextStudy() {
23 const [count, setCount] = useState(5);
24 const add = () => {
25 setCount(count + 1);
26 };
27 // 2. 需要一个Provider
28 return (
29 <MyContext.Provider value={{ count, add }}>
30 <Parent />
31 </MyContext.Provider>
32 );
33 }
34
35 function Parent() {
36 return <Child />;
37 }
38
39 function Child() {
40 const data = useContext(MyContext);
41 console.log(data);
42 return (
43 <div>
44 <h3>孙子</h3>
45 <p>{data.count}</p>
46 <button onClick={data.add}>++</button>
47 </div>
48 );
49 }
RefHook
在函数组件里面我们可以使用userRef这个Hook获取一个元素或者组件的引用
1 import React, { useEffect, useRef } from "react";
2
3 export default function RefHook() {
4 const btn = useRef();
5 // 在componentDidMount后获取
6 useEffect(() => {
7 console.log(btn.current);
8 }, []);
9 return (
10 <div>
11 <button ref={btn}>Button</button>
12 </div>
13 );
14 }
ReducerHook
useReducer是useState的替代方案,当useState里面的逻辑相对复杂的时候,我们可以使用useReducer来代替。
useRducer的基本使用步骤如下:
a.准备一个初始state数据和操作state的方法
1 // 初始state
2 const state = {
3 count: 0,
4 };
5 // 操作state的方法reducer
6 // aciont里面一般是type和pyload两个属性用来判断不同的复杂逻辑
7 const reducer = (st = state, action) => {
8 const state = JSON.parse(JSON.stringify(st));
9 // 通过判断不同的action来处理不同的逻辑
10 switch (action.type) {
11 case "add":
12 state.count += action.pyload;
13 break;
14 case "reduce":
15 state.count -= action.pyload;
16 break;
17 }
18 // reducer一定要返回一个新的state
19 return state;
20 };
b.调用useReducer这个Hook来得到state和dispatch
export default function ReducerHook() {
// state就是我们需要维护的数据,dispatch是一个方法,用来调用reducer的
const [state, dispatch] = useReducer(reducer, initState);
return (
<div>
<div>ReducerHook</div>
<div>state's count : {state.count}</div>
{/* dispatch方法传入一个action来激活reducer里面对应的操作 */}
<button onClick={() => dispatch({ type: "add", pyload: 1 })}>Add</button>
<button onClick={() => dispatch({ type: "reduce", pyload: 1 })}>
reduce
</button>
</div>
);
}
其它Hook
上述的那些已经是我们平时比较常用的hook,当然hook不是只有这些,如果想了解,戳这里
练手小目标:
1.能使用useState实现函数式组件的响应式数据。
2.能使用useContext实现多级组件间的数据传递。
3.能使用useEffect模拟生命周期。
4.能使用useRef获取DOM元素的引用。
5.能使用useReducer实现响应式数据操作。
开发中常用的Hook的更多相关文章
- .net开发中常用的第三方组件
.net开发中常用的第三方组件 2013-05-09 09:33:32| 分类: dotnet |举报 |字号 订阅 下载LOFTER 我的照片书 | RSS.NET.dll RSS. ...
- 依赖注入及AOP简述(十)——Web开发中常用Scope简介 .
1.2. Web开发中常用Scope简介 这里主要介绍基于Servlet的Web开发中常用的Scope. l 第一个比较常用的就是Application级Scope,通常我们会将一 ...
- spring注解开发中常用注解以及简单配置
一.spring注解开发中常用注解以及简单配置 1.为什么要用注解开发:spring的核心是Ioc容器和Aop,对于传统的Ioc编程来说我们需要在spring的配置文件中邪大量的bean来向sprin ...
- Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令
Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...
- 2019-2-20C#开发中常用加密解密方法解析
C#开发中常用加密解密方法解析 一.MD5加密算法 我想这是大家都常听过的算法,可能也用的比较多.那么什么是MD5算法呢?MD5全称是 message-digest algorithm 5[|ˈmes ...
- 开发中常用的es6知识
结合实际开发,开发中常用的es6的知识: 1.新增let和const命令: ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效: cons ...
- Android开发中常用的库总结(持续更新)
这篇文章用来收集Android开发中常用的库,都是实际使用过的.持续更新... 1.消息提示的小红点 微信,微博消息提示的小红点. 开源库地址:https://github.com/stefanjau ...
- iOS开发中常用的数学函数
iOS开发中常用的数学函数 /*---- 常用数学公式 ----*/ //指数运算 3^2 3^3 NSLog(,)); //result 9 NSLog(,)); //result 27 //开平方 ...
- Struts2页面开发中常用标签使用说明
1. Struts2页面开发中常用标签使用说明 1.1.往action里传值的使用方式: <input name="userName" type="text&quo ...
随机推荐
- 2022 年最受瞩目的新特性 CSS @layer 到底是个啥?
步入 2022,CSS 的新特性层出不穷,而最近在 CSS 圈最受瞩目的新特性,非 CSS @layer 莫属. 本文,将用最简洁的语言,快速让读者们搞懂,到底什么是 CSS @layer 新规范. ...
- 遇到REMOTE HOST IDENTIFICATION HAS CHANGED怎么办?
今日遇到如下问题: 警告的大概意思就是,主机密钥发生变更,并提示安全风险(可能存在中间人攻击) 但是事实是,这是因为我重装系统之后遇到的问题.重装系统后,指纹当然会发生变化了...在Xshell实验中 ...
- minouche
靶机准备 先将靶机导入虚拟机,并将网络模式改为NAT 扫描不到ip,改VirtualBox,使用桥接,并将kali也改为桥接模式 扫描ip:192.168.0.102 netdiscover -r 1 ...
- c# / .net wFramework winform 之运行后的窗体窗口可拖动操作
学习winform 的同志们可能会有这样的提问,我运行起来的窗体或者窗口该如何实现可拖动呢?今天它来了 思路:可以给窗体增加一个进度条(progressBar控件) 全局定义这几个变量: long p ...
- Windows10与Centos7双系统安装踩的坑
1. 首先安装windows(太简单不说了) 2.然后安装Centos7(太简单不说了) 3.注意:安装完Centos7重启电脑进入系统引导项突然发现没有Windows引导项 0x06 恢复Windo ...
- Java中的list和set有什么区别
list与set方法的区别有:list可以允许重复对象和插入多个null值,而set不允许:list容器是有序的,而set容器是无序的等等 Java中的集合共包含三大类,它们分别是Set(集),Lis ...
- 说说has a与is a的区别?
is a是典型的"一般到特殊"的关系,也就是典型的继承关系.例如Apple is a Fruit.那么Apple是一种特殊的Fruit,也就是说Apple继承了Fruit. has ...
- ServletConfig对象和ServletContext对象有什么区别?
一个Servlet对应有一个ServletConfig对象,可以用来读取初始化参数. 一个webapp对应一个ServletContext对象. ServletContext对象获取初始化定义的参数. ...
- kafka 分布式(不是单机)的情况下,如何保证消息的顺序消费?
Kafka 分布式的单位是 partition,同一个 partition 用一个 write ahead log 组织, 所以可以保证 FIFO 的顺序.不同 partition 之间不能保证顺序. ...
- Ribbon负载均衡能干什么?
(1)将用户的请求平摊的分配到多个服务上 (2)集中式LB即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至 ...