如何优雅地使用React Hooks

一、理解什么是Hooks

在React中,Hooks其实就是一个函数,这个函数的命名以use开头、函数return一个结果;React Hooks其实就是封装了一些通用的、公共的方法,就是一些通用的工具。

二、React Hooks分为官方Hooks和自定义Hooks

官方Hooks是指React官方推荐的一些Hooks,如:useState、useEffect、useContext、useRef、useMemo、useCallback、useReducer、......;

1.useState:让React函数组件也可以使用状态,使用方法:const [ age, setAge ] = useState(35).

2.useEffect:在React函数组件里,没有组件生命周期这一说法,所以可以使用useEffect来替代组件生命周期,使用方法如下:

useEffect( () => {window.addEventListener('message', handleMessage );return () => {window.removeEventListener('message', handleMessage );}
}, [] )

useEffect接收的一个回调函数相当于是componentDidMount和componentDidUpdate,回调函数return的这一个回调相当于是componentWillUnmount;useEffect接收的第二个数组是依赖项,如果只是模拟组件生命周期,可以传空数组,通常这个依赖项不要传入过多或过于复杂,因为当依赖项发生变化useEffect中的回调函数会重新执行。

3.useContext:用于父组件向子组件的跨级传参,使用比较简单,直接参考官方文档即可。

4.useRef:绑定元素ref,通常用于调用子组件身上的方法;this.formRef.current.doReq()...。

5.useMemo:用于缓存函数的计算结果,与Vue中的计算属性类似;使用方法如下:

const result = useMemo( () => {const res = a + b;return res;
}, [a,b] )

useMemo的第二个参数为依赖项数组,依赖项发生变化则重新计算结果。

6.useCallback:缓存函数(缓存函数地址),通常与React.memo()一起使用;React.memo()是通过校验props中的数据是否改变的来决定组件是否需要重新渲染的一种缓存技术,具体点说React.memo()其实是通过校验Props中的数据的内存地址是否改变来决定组件是否重新渲染组件的一种技术。useCallback通常用于缓存父组件向子组件传递的函数,当父组件发生变化时会重新渲染,此时若变化与子组件无关,子组件不应重复渲染;useCallBack并不能阻止函数重新创建,它只能通过依赖决定返回新的函数还是旧的函数,从而在依赖不变的情况下保证函数地址不变。其使用方法如下:

import {useCallBack,memo} from 'react';const Parent = ( props ) => {const [parentData, setParentData] = useState(66);  const toChildFun = useCallBack( () => {console.log("需要传入子组件的函数");}, [])return (<div><Button onClick={() => setParentState(val => val+1)}>点击改变父组件中与Child组件无关的state</Button><Child fun={toChildFun}></Child><div>)
}const Child = memo(( props ) => {console.log('子组件渲染了');return <div>子组件<div>
} )

7.useReducer:相当于写redux,直接根据官方文档进行使用。

官方文档里还有一些其他的Hooks,其实使用起来都比较方便,直接看文档使用就行了,在这里就列举以上几种常用的官方Hooks。

自定义Hooks其实就是根据自己的开发需求,封装一些通用的、公共的工具函数,使用起来其实就和官方推荐的Hooks是一样的。

自定义 Hooks 允许共享有状态逻辑,而不是状态本身,例如:

import { useState } from 'react';
// 自定义Hooks 
function useCounter(initialValue) {const [count, setCount] = useState(initialValue);function increment() {setCount(count + 1);}return [count, increment];
}// 在其他组件进行使用
import useCounter from './useCounter';
function Counter() {const [count1, increment1] = useCounter(0);const [count2, increment2] = useCounter(100);return (<div><p>Count1: {count1}</p><button onClick={increment1}>Increment1</button><p>Count2: {count2}</p><button onClick={increment2}>Increment2</button></div>);
}

当我们点击 Increment2 时,并不会影响 count1 ,因为每一个 useCounter 的调用都是独立的,其内部状态也是独立的。

三、React Hooks使用方法

1.只能在函数外层调用 Hook,不要在循环、条件判断或者子函数中调用。

2.只能在 React 的函数组件(顶部)和自定义 Hook 中调用 Hook。不要在其他 JavaScript 函数中调用。

3.在组件中 React 是通过判断 Hook 调用的顺序来判断某个 state 对应的 useState的,所以必须保证 Hook 的调用顺序在多次渲染之间保持一致,React 才能正确地将内部 state 和对应的 Hook 进行关联。

四、用Hooks替代一些高阶组件会更有优势

假如现在我们要让多个组件复用一个基于状态的逻辑公共方法:

1.使用高阶组件

import { Table } from 'antd'
import server from './server'function useTable(server) {return function (WrappedComponent) {return class HighComponent extends React.Component {state = {tableProps: xxx, };render() {const { tableProps } = this.state;return <WrappedComponent tableProps={tableProps} />;}};};
}@useTable(server)
class App extends Component{render(){const { tableProps } = this.props;return (<Table columns={[...]}{...tableProps}/>)}
}

2.使用Hooks

import { Table } from 'antd'
import server from './api'function useTable(server) {const [tableProps, setTableProps] = useState(xxx);return tableProps;
}function App {const { tableProps } = useTable();return (<Table columns={[...]}{...tableProps}/>)
}

使用Hooks可以减少组件树的层级,防止组件深度嵌套,同时代码也更少更简洁。

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

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

相关文章

机器学习中的嵌入:释放表征的威力

简介 机器学习通过使计算机能够从数据学习和做出预测来彻底改变了人工智能领域。机器学习的一个关键方面是数据的表示&#xff0c;因为表示形式的选择极大地影响了算法的性能和有效性。嵌入已成为机器学习中的一种强大技术&#xff0c;提供了一种捕获和编码数据点之间复杂关系的…

二维码智慧门牌管理系统全新升级:个性化配置,智能管理,让你的社区更安全!

文章目录 前言一、个性化配置功能的升级二、智能化管理和便捷性 前言 随着科技的飞速发展&#xff0c;智能化管理已经成为各个领域的标配。在社区管理方面&#xff0c;智能化的优势在便捷性、高效性和安全性方面得到了广泛认可。最近&#xff0c;二维码智慧门牌管理系统经过全…

Flutter 常见错误记录总结

1、当 flutter pub get 指令报如下错误时&#xff1a; pub get failed command: "/Users/***/developer/flutter/bin/cache/dart-sdk/bin/dart __deprecated_pub --color --directory . get --example" pub env: { "FLUTTER_ROOT": "/Users/***/dev…

SpringBoot整合JUnit

1.创建新项目 说明&#xff1a;创建springboot_04_junit项目&#xff0c;选择对应的版本。 2.接口类 说明&#xff1a;新建BookDao接口。 package com.forever.dao;public interface BookDao {public void save(); }3.实现类 说明&#xff1a; 新建BookDaoImpl实现类。 pa…

npm发布自己的包

npm发布自己的包 1. 首先在npm官网注册一个自己的账户(有账号的可以直接登录) 注册地址 2. 创建一个自己的项目(如果已有自己的项目, 跳过这一步) npm init -y3. 确认自己的npm下载源, 只能使用npm官方的地址 npm config get registry修改地址源 npm config set registr…

洛谷P1102 A-B数对 详细解析及AC代码

P1102 A-B数对 前言题目题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题目分析注意事项 代码经典二分&#xff08;O(nlgn)&#xff09;酷炫哈希&#xff08;O(n)&#xff09; 后话额外测试用例样例输入 #2样例输出 #2 王婆卖瓜 题目来源 前言 酷&…

DASCTF X CBCTF 2023|无畏者先行

前言 笔者没有参加此次比赛&#xff0c;由于团队后面会复现此次比赛&#xff0c;所以笔者在此进行复现记录。 EASYBOX 考点&#xff1a;命令执行&#xff1f; 栈溢出 附件给了 docker 环境&#xff0c;可以直接在本地复现&#xff0c;但是 docker 我不会调试&#xff0c;幸…

11.Z-Stack协议栈使用

f8wConfig.cfg文件 选择信道、设置PAN ID 选择信道 #define DEFAULT_CHANLIST 0x00000800 DEFAULT_CHANLIST 表明Zigbee模块要工作的网络&#xff0c;当有多个信道参数值进行或操作之后&#xff0c;把结果作为 DEFAULT_CHANLIST值 对于路由器、终端、协调器的意义&#xff1…

react: antd组件使用 FC Fragment

RangePicker const defaultDate 2021-22-16 const [reportDate, setReportDate] useState<any>([defaultDate , defaultDate]);<RangePickerstyle{{width: 260px}}placeholder{[开始日期, 结束日期]}allowClear{false}defaultValue{[defaultDate, defaultDate]}va…

Java代码Demo——Map根据key或value排序

Map根据key排序 升序 Demo代码&#xff1a; //使用TreeMap Map<Integer, String> map new TreeMap<>(); map.put(10, "第10名次"); map.put(15, "第15名次"); map.put(1, "第1名次"); map.put(5, "第5名次"); map.put…

Spring boot集成sentinel限流服务

Sentinel集成文档 Sentinel控制台 Sentinel本身不支持持久化&#xff0c;项目通过下载源码改造后&#xff0c;将规则配置持久化进nacos中&#xff0c;sentinel重启后&#xff0c;配置不会丢失。 架构图&#xff1a; 改造步骤&#xff1a; 接着我们就要改造Sentinel的源码。…

U盘显示无媒体怎么办?方法很简单

当出现U盘无媒体情况时&#xff0c;您可以在磁盘管理工具中看到一个空白的磁盘框&#xff0c;并且在文件资源管理器中不会显示出来。那么&#xff0c;导致这种问题的原因是什么呢&#xff1f;我们又该怎么解决呢&#xff1f; 导致U盘无媒体的原因是什么&#xff1f; 当您遇到上…

SLAM从入门到精通(被忽视的基础图像处理)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 工业上用激光slam的多&#xff0c;用视觉slam的少&#xff0c;这是大家都知道的常识。毕竟对于工业来说&#xff0c;健壮和稳定是我们必须要考虑的…

Pytorch 快速参数权重初始化

定义一个函数&#xff1a; 这里比如要初始化2维卷积权重值&#xff0c;采用xaiver 数据分布&#xff0c;还有很多其他的数据分布可以探索 def weights_init(m):if isinstance(m, nn.Conv2d):xavier(m.weight.data)xavier(m.bias.data) 然后定义一个含2维卷积的网络&#xff…

Zinx框架-游戏服务器开发002:框架学习-按照三层结构模式重构测试代码+Tcp数据适配+时间轮定时器

文章目录 1 Zinx框架总览2 三层模式的分析3 三层重构原有的功能 - 头文件3.1 通道层Stdin和Stdout类3.1.2 StdInChannel3.1.2 StdOutChannel 3.2 协议层CmdCheck和CmdMsg类3.2.1 CmdCheck单例模式3.2.1.1 单例模式3.2.1.2 * 命令识别类向业务层不同类别做分发 3.2.2 CmdMsg自定…

【Mac开发环境搭建】JDK安装、多JDK安装与切换

文章目录 JDK下载与安装下载安装 配置环境变量安装多个JDK共存 JDK下载与安装 下载 Oracle官网提供了非常多个版本的JDK供下载&#xff0c;可以点击如下链接重定向到JDK下载页面 ORACLE官网JDK下载 安装 下面的官方文档可以点开收藏到浏览器的收藏夹&#xff0c;这样后续在开…

Ribbon讲解

一&#xff1a;Ribbon是什么&#xff1f; Ribbon其实就是一个软负载均衡的客户端组件。 二&#xff1a;负载均衡(LB)是什么&#xff1f; 用户的请求平摊的分配到多个服务上&#xff0c;从而达到系统的HA&#xff08;高可用&#xff09; 三&#xff1a;负载均衡分类&#xf…

Android Studio(控件常用属性)

通用属性 属性描述android:id用于为视图指定唯一的标识符。android:layout_width用于指定视图的宽度。android:layout_height用于指定视图的高度。android:layout_margin用于指定视图周围的空白区域。android:layout_padding用于指定视图内部的填充区域。android:background用…

思维模型 锚定效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。先入为主&#xff0c;决策易偏。 1 锚定效应的应用 1.1 定价策略中的锚定效应 黑珍珠的定价策略&#xff1a;在 20 世纪 70 年代&#xff0c;黑珍珠被视为一种廉价的珠宝。然而&#xff…

[算法日志]图论: 广度优先搜索(BFS)

[算法日志]图论&#xff1a; 广度优先搜索(BFS) 广度优先概论 ​ 广度优先遍历也是一种常用的遍历图的算法策略&#xff0c;其思想是将本节点相关联的节点都遍历一遍后才切换到相关联节点重复本操作。这种遍历方式类似于对二叉树节点的层序遍历&#xff0c;即先遍历完子节点后…