开发中常用的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. 版本控制工具之git的常用命名01

    基本命令 从git远程仓库导出项目:git clone http://127.0.0.1/name_master/server.git 从git远程仓库拉取代码:git pull 查看本地仓库状态:g ...

  2. Betaflight Configurator开源仓库说明-中文版

    Betaflight Configurator Betaflight Configurator是Betaflight飞行控制系统的跨平台配置工具. 它在Google Chrome中作为应用程序运行,允 ...

  3. Flutter查漏补缺1

    Flutter 基础知识查漏补缺 Hot reload原理 热重载分为这几个步骤 扫描项目改动:检查是否有新增,删除或者改动,直到找到上次编译后发生改变的dart代码 增量编译:找到改变的dart代码 ...

  4. 阐述final、finally、finalize的区别?

    - final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词.将变量声明为final,可以保证它们在使用中不被 ...

  5. memcached 最大的优势是什么?

    Memcached 最大的好处就是它带来了极佳的水平可扩展性,特别是在一个巨大的 系统中.由于客户端自己做了一次哈希,那么我们很容易增加大量 memcached 到集群中.memcached 之间没有 ...

  6. Jedis 与 Redisson 对比有什么优缺点?

    Jedis 是 Redis 的 Java 实现的客户端,其 API 提供了比较全面的 Redis 命令 的支持:Redisson 实现了分布式和可扩展的 Java 数据结构,和 Jedis 相比,功能 ...

  7. 学习zabbix(五)

    前言 zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.zabbix组件主要分两个: zabbix-server和zabbix-agent.支持的监控协议有I ...

  8. 语言算子&模糊推理

    一.语言算子 语言算子分为三类: ①语气算子 ②模糊化算子 ③判定化算子 (1)语气算子 "集中化算子":--"很"."极"."非 ...

  9. C语言小游戏——2048

      2048   2048这款游戏的玩法很简单,每次可以选择上下左右滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢.相撞时会相加. ...

  10. 【转】ng-class的用法

    原文出处:https://segmentfault.com/a/11... 在开发中我们通常会遇到一种需求:一个元素在不同的状态需要展现不同的样子. 而在这所谓的样子当然就是改变其css的属性,而实现 ...