开发中常用的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 ...
随机推荐
- Objects.equals有坑
前言 最近review别人代码的时候,发现有个同事,在某个业务场景下,使用Objects.equals方法判断两个值相等时,返回了跟预期不一致的结果,引起了我的兴趣. 原本以为判断结果会返回true的 ...
- java-Markdown学习
Markdown学习 标题 三级标题 四级标题 字体 Hello world! Hello world! Hello world! Hello world! 引用 L-1906 分割线 图片 超链接 ...
- JavaWeb 03_创建servlet项目(详细)
一.创建web项目 1. File--New--Project 2. 设置项目相关信息 3. 设置项目名称及工作空间 4. web项目目录结构如下 二.Servlet的实现 1. 新建包---类 ...
- TypeScript 初体验
TypeScript学习 1 安装环境 a 首先安装node.js node.js 用来将ts文件解析成js文件 供浏览器使用: 解析ts文件 tsc filename.ts b. 使用npm (no ...
- 查看mysql是否开启慢查询
说明: slow_query_log 慢查询开启状态 slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录) l ...
- 如何做一个网站 (C# + MVC Web+ easyUI )
如何做一个网站 小编想做一个网站,采用技术为:C# + MVC Web+ easyUI 小编经过几天的学习,以及指了几位大神指导,初见效果.建立网站的思路:先列举需要用到了几个知识点,然后逐一攻克,然 ...
- 到底为什么不建议使用SELECT *?
"不要使用SELECT *"几乎已经成为了MySQL使用的一条金科玉律,就连<阿里Java开发手册>也明确表示不得使用*作为查询的字段列表,更是让这条规则拥有了权威的加 ...
- Java 中的 ReadWriteLock 是什么?
读写锁是用来提升并发程序性能的锁分离技术的成果.
- DRF(Django REST Framework)框架
目录 一.DRF中的Request 二.前戏: 关于面向对象的继承 三.初级版本 1. settings.py文件 -- 注册app 2. models.py文件 -- 创建表 3. admin.py ...
- 学习heartbeat-02安装及配置
2.部署Heartbeat高可用需求 2.1 操作系统 CentOS-6.8-x86_64 2.2 Heartbeat服务主机资源准备 主服务器A: 主机名:heartbeat-1-130 eth0网 ...