开发中常用的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 进行多级组件传递数据

用法:

  1. createContext

  1. Provider

  1. 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的更多相关文章

  1. .net开发中常用的第三方组件

    .net开发中常用的第三方组件 2013-05-09 09:33:32|  分类: dotnet |举报 |字号 订阅     下载LOFTER 我的照片书  |   RSS.NET.dll RSS. ...

  2. 依赖注入及AOP简述(十)——Web开发中常用Scope简介 .

    1.2.    Web开发中常用Scope简介 这里主要介绍基于Servlet的Web开发中常用的Scope. l        第一个比较常用的就是Application级Scope,通常我们会将一 ...

  3. spring注解开发中常用注解以及简单配置

    一.spring注解开发中常用注解以及简单配置 1.为什么要用注解开发:spring的核心是Ioc容器和Aop,对于传统的Ioc编程来说我们需要在spring的配置文件中邪大量的bean来向sprin ...

  4. Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

    Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...

  5. 2019-2-20C#开发中常用加密解密方法解析

    C#开发中常用加密解密方法解析 一.MD5加密算法 我想这是大家都常听过的算法,可能也用的比较多.那么什么是MD5算法呢?MD5全称是 message-digest algorithm 5[|ˈmes ...

  6. 开发中常用的es6知识

    结合实际开发,开发中常用的es6的知识: 1.新增let和const命令: ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效: cons ...

  7. Android开发中常用的库总结(持续更新)

    这篇文章用来收集Android开发中常用的库,都是实际使用过的.持续更新... 1.消息提示的小红点 微信,微博消息提示的小红点. 开源库地址:https://github.com/stefanjau ...

  8. iOS开发中常用的数学函数

    iOS开发中常用的数学函数 /*---- 常用数学公式 ----*/ //指数运算 3^2 3^3 NSLog(,)); //result 9 NSLog(,)); //result 27 //开平方 ...

  9. Struts2页面开发中常用标签使用说明

    1. Struts2页面开发中常用标签使用说明 1.1.往action里传值的使用方式: <input name="userName" type="text&quo ...

随机推荐

  1. 巧用"记事本"让病毒无效运行

    电脑中毒后,许多朋友会打开"进程管理器",将几个不太熟悉的程序关闭掉,但有时会碰到这种情况:关掉一个, 再去关闭另外一个时,刚才关闭的那个马上又运行了.再从注册表里先把启动项删除后 ...

  2. 网络编程 基础 基于socket的tcp和udp连接

    网络开发的框架 C/S B/S 架构 程序都是bs架构的程序(b指浏览器,s指服务器) c(client)是客户端,s(server)是服务器 bs架构是cs架构的一种 未来的趋势, pc端bs架构, ...

  3. 数据类型 Java day7

    数据类型 数据类型包含:引用数据类型和基本数据类型 引用数据类型:出去基本数据类型,其他的类型,如String 基本数据类型:总共分四大类有八种 四大类:整数,浮点数.字符.布尔 一.整数包含以下 数 ...

  4. 接口(interface)与抽象类(abstract class)两者的异同

    首先说明一下,JDK1.8以后接口可以有默认方法和静态方法以及私有方法. 一.概念: 接口(interface):是抽象类的变体,其中所有的方法都是抽象的且不能有方法体,而且只能定义 static f ...

  5. Java锁之乐观锁、悲观锁、自旋锁

    java锁分为三大类乐观锁.悲观锁.自旋锁 乐观锁:乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别 ...

  6. JSP和Servlet有哪些相同点和不同点?

    JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达.JSP编译后是"类servlet". Servlet和JSP最主要的不同点在于,Servl ...

  7. Java 中堆和栈有什么区别?

    JVM 中堆和栈属于不同的内存区域,使用目的也不同.栈常用于保存方法帧和局 部变量,而对象总是在堆上分配.栈通常都比堆小,也不会在多个线程之间共享, 而堆被整个 JVM 的所有线程共享.

  8. 什么是持续集成CI?

    持续集成(CI)是每次团队成员提交版本控制更改时自动构建和测试代码的过程. 这鼓励开发人员通过在每个小任务完成后将更改合并到共享版本控制存储库来共 享代码和单元测试.

  9. IIS在ASP.NET Core下的两种部署模式

    KestrelServer最大的优势体现在它的跨平台的能力,如果ASP.NET CORE应用只需要部署在Windows环境下,IIS也是不错的选择.ASP.NET CORE应用针对IIS具有两种部署模 ...

  10. List集合工具类之"将list集合按"指定长度"进行切分Lists.partition和ListUtils.partition"

    将list集合按"指定长度"进行切分,返回新的List<List<类型>>集合,如下的:  方法1:List<List<Integer>& ...