当前位置: 首页 > news >正文

弄懂自定义 Hooks 不难,改变开发认知有点不习惯

前言

我之前总结逻辑重用的时候,就一直在思考一个问题。

对于逻辑复用,render props 和 高阶组件都可以实现,同样官方说 Hooks 也可以实现,且还是在不增加额外的组件的情况下。

但是我在项目代码中,没有找到自定义 Hooks 的身影,自己也很少写。所以是为什么呢?

遇到问题表示查漏补缺的机会来了。

遇到技术点先问几个为什么

偶尔我会先问自己几个为什么,然后去寻找答案。带着明确的目标,不容易漏掉重要的讯息。

1.什么是自定义 Hooks?很难实现吗?
2.自定义 Hooks 和普通函数有什么区别?
3.如何创建一个自定义 Hook?
4.为什么需要自定义 Hooks?哪些场景会用到?
5.为什么我好像平时用不到?

自定义 Hooks 很难吗?

自定义 hooks可以看做是 React Hooks 的之外的自由延伸。本质上还是 JavaScript 函数。主要用途是实现逻辑重用。

React Hooks、函数、逻辑重用,根据这些关键字观察,实现自定义 Hooks 应该不是很难。

自定义 Hooks 和普通函数有什么区别?

看了关于自定义 Hooks 的介绍,我冒出来了第二个小问号:

这跟普通的逻辑复用函数有什么区别呢?

于是,我认真阅读了React的官方文档,发现主要有两点区分:

  • 名字应该始终以 use 开头。
  • 在自定义 Hook 中调用其他 Hook。

如何创建一个自定义 Hook?

因为Hook 本质是 JavaScript 函数,所以创建自定义 Hook其实就是声明一个名字以 use 开头的函数。

useDateRange

这个自定义 Hook 的过程算是意外惊喜,我在看完官方的例子之后,一直在想我实际开发中有哪些部分可以通过自定义 Hook实现逻辑的重用。

然后意外发现了项目中存在的可优化空间,后续会陆续产出优化的经验。

这里我先以项目中常出现的日期选择器为例,演示一下创建自定义 Hook 的全过程。

自定义 Hook 介绍

当前的需求如下:

  • 日期选择器,需要设置可选日期范围,超出1天~10天的范围不可选择。
  • 选择某个日期之后,需要计算跟当天日期相差的天数,并回显到页面上。

注:日期选择器使用的 antd 提供的组件,所有的参数均可以在官网查看。

UI 效果

可选日期效果

相差天数回显

可复用逻辑提取

可复用的逻辑主要包括三个部分:日期选择器的可选限制、时间发生变化的回调函数、相差天数变量。

日期选择器的可选限制

moment.js 的 add 方法可以计算指定时间之后(或之前)的某个时间。结合 startOf 方法和 endOf 方法使用,可以确定可选范围的起始日期。

时间发生变化的回调函数

当选定日期的时候,回调函数会返回选中的日期。

相差天数

通过时间回调函数拿到当前选择的日期,使用 moment.js 的 diff 方法,与今天的日期做比较。diff 方法的第二个参数决定差值的度量单位,day表示天数。

/*** @description 时间选择器的限制和相差天数*/
import React, { useState, useCallback, useMemo } from 'react';
import moment from 'moment';const useDateRange = () => {// 相差天数let [dayDiff, setDayDiff] = useState(0);/** * 可选时间范围 1~10 */const disabledDate = useCallback(current => {const startTimer = moment().add(+1, 'days').startOf('day');const endTimer = moment().add(+10, 'days').endOf('day');return current && (current < startTimer || current > endTimer);}, []);/** * 时间选择器选择操作 获取相差天数 */const dateChange = useCallback(dates => {let nowDate = new Date();let startData = moment(nowDate).format('YYYY-MM-DD');let endData = moment(dates).format('YYYY-MM-DD');dayDiff = moment(endData).diff(moment(startData), 'day');setDayDiff(dayDiff);}, []);return { dayDiff, disabledDate, dateChange };
};
export default useDateRange; 

使用 useDateRange

引入自定义的 useDateRange 这个 Hook,就可以拿到传入的参数了。

/*** @description 日期选择页*/
import React from 'react';
import { DatePicker } from 'antd';
import useDateRange from './hooks/useDateRange';const ChangeDatePage = () => {// 使用自定义 Hookconst { disabledDate, dateChange, dayDiff } = useDateRange();return (<div><DatePicker disabledDate={disabledDate} onChange={dateChange} /><div className="mt20">选择的日期与今天相差: {dayDiff} 天</div></div>);
};export default ChangeDatePage; 

自定义 Hooks 的优势和使用场景

等了解了它的优势,基本也就能联想到有哪些使用场景。

优势

自定义 Hooks 主要有两点优势:

  • 逻辑复用
  • 复杂代码分离

使用场景

通过对自定义 Hooks 了解和使用,可以归纳的使用场景主要包括三个大类:

封装可复用的逻辑、监听数据的状态、拆分复杂的逻辑

基于这三类场景,可应用的地方应该不少。未来一段时间,我准备改造一下我们的项目代码,这下事情开始有趣了。

为什么我好像平时用不到?

为何纠结用不到这件事?

先简单说一下最近为什么一直纠结用不到这件事。因为身处「业务驱动技术」的技术科技公司,业务迭代是很迅速的,想在快节奏的开发中,整个前端团队保持一个较高水平的开发水平,不是很容易。

想在逻辑复用上下一些功夫,提升开发效率,团队成员可以腾出一些时间进行技术升级。

开发认知

自定义 Hooks 和普通函数的界限是可变的,加上平时开发的命名不太习惯用 use 开头。

所以用到的少,并不是因为自定义 Hooks 的开发难度或者开发者技术水平,而是改变这个开发认知有点不习惯。

但是个人认为改变是有帮助的。

  • 已知自定义 Hooks 主要用途是进行逻辑复用,那么从 use 开头的函数名,使用者不难联想到该函数方法是不是封装了某个公共的逻辑。
  • 其实除了逻辑复用,复杂逻辑的拆分,也可以考虑用自定义 Hooks 实现。

今日总结

今天除了清楚自定义 Hooks的相关知识点、如何创建以及使用场景。还帮助我衍生了新的开发思路,让我对原以为无法进行逻辑复用的功能,有了新的想法。

后面如果有了更好的开发思路,会持续输出文章分享出来。

彩蛋

今天的彩蛋,讲个之前困扰过我问题以及后来我总结出来的经验。

现阶段一直在写业务代码,感觉技术上没有得到什么提升?

我之前也被这个问题困扰过。后来,我从身边很多优秀的思维中,总结了一些经验,也就不再纠结这个问题。

误区在哪?

技术和业务的关系,不是对立面,而是相辅相成、相得益彰的。尤其现在大多数是业务驱动型公司。已知「技术可推动业务的发展」,同样的业务日趋繁复,倒逼技术的更迭。

日复一日重复的功能?

遇到这个困惑时,不排除一种可能,受思维定式的影响,重复之前的实现方式。

但是功能本身未必不能用更好的方式去实现。

举个例子,搜索项常见于表格页面,因为每个页面的搜索项都不太一样,很长一段时间,都被散落在各个页面中。其实搜索项的类型基本就那几种,于是有同事封装了一个公共组件,只需要传入包含搜索项基础信息的配置数组变量即可。

以前散落在每个页面的搜索项,如果再加上事件的处理,冗余代码量会更多。

<div><label>城市:</label><Input placeholder='请输入城市' />
</div>
<div><label>分类:</label><Select placeholder='请选择'><Select.Option key='1'>分类1</Select.Option><Select.Option key='2'>分类2</Select.Option></Select>
</div> 

后来封装成公共组件之后,代码简洁了很多,且大部分逻辑处理在组件中,使用时开发者并不用关心这些。

const fields = [{label: '城市',fieldtype: 'input',},{label: '分类',fieldtype: 'select',option: [{key: 1,value: '分类1'},{key: 2,value: '分类2'},]},
]
<Search fields={fields} /> 

工作中找不到项目练手?

我把日常的经验总结为:主动出击和没有条件创造条件。

  • 如果有一定的能力,可以申请功能立项或者参与一些工程化建设项目。自己主动把握机会。
  • 追随开拓者,自己创造条件。从模仿优秀的开源的项目到开发属于自己独立思维的项目过度,也是一个不错的选择。

总结时刻

三个问题和三个解答,解铃还须系铃人,心结还需自己解。

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

相关文章:

弄懂自定义 Hooks 不难,改变开发认知有点不习惯

前言 我之前总结逻辑重用的时候&#xff0c;就一直在思考一个问题。 对于逻辑复用&#xff0c;render props 和 高阶组件都可以实现&#xff0c;同样官方说 Hooks 也可以实现&#xff0c;且还是在不增加额外的组件的情况下。 但是我在项目代码中&#xff0c;没有找到自定义 …...

Java面向对象基础

文章目录面向对象类注意事项内存机制构造器this关键字封装javabean格式成员变量和局部变量区别static静态关键字使用成员方法使用场景内存机制注意事项static应用&#xff1a;工具类static应用&#xff1a;代码块静态代码块实例代码块&#xff08;用的比较少&#xff09;static…...

基于python下selenium库实现交互式图片保存操作(批量保存浏览器中的图片)

Selenium是最广泛使用的开源Web UI&#xff08;用户界面&#xff09;自动化测试套件之一&#xff0c;可以通过编程与浏览量的交互式操作对网页进行自动化控制。基于这种操作进行数据保存操作&#xff0c;尤其是在图像数据的批量保存上占据优势。本博文基于selenium 与jupyterla…...

一:Datart的下载、本地运行

前言&#xff1a;本文只是个人在使用datart的一个记录&#xff0c;仅供参考。如果有不一样的地方&#xff0c;欢迎评论或私信进行交流。datart 是新一代数据可视化开放平台&#xff0c;支持各类企业数据可视化场景需求&#xff0c;如创建和使用报表、仪表板和大屏&#xff0c;进…...

Docker-compose

一.Docker-compose概述Docker-Compose项目是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排。Docker-Compose将所管理的容器分为三层&#xff0c;分别是 工程&#xff08;project&#xff09;&#xff0c;服务&#xff08;service&#xff09;以及容器&a…...

经典文献阅读之--PLC-LiSLAM(面,线圆柱SLAM)

0. 简介 对于激光SLAM来说&#xff0c;现在越来越多的算法不仅仅局限于点线等简答特征的场景了&#xff0c;文章《PLC-LiSLAM: LiDAR SLAM With Planes, Lines,and Cylinders》说到&#xff0c;平面、线段与圆柱体广泛存在于人造环境中。为此作者提出了一个使用这些landmark的…...

计算组合数Cnk即从n个不同数中选出k个不同数共有多少种方法math.comb(n,k)

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 计算组合数Cnk 即从n个不同数中选出k个不同数共有多少种方法 math.comb(n,k) 以下python代码输出结果是? import math print("【执行】print(math.comb(3,1))") print(math.comb(…...

工厂设计模式

基本概念&#xff1a;为创建对象提供过渡接口&#xff0c;以便将创建对象的具体过程屏蔽隔离起来&#xff0c;达到提高灵活性的目的。分为三类&#xff1a;简单工厂模式Simple Factory&#xff1a;不利于产生系列产品&#xff1b;工厂方法模式Factory Method&#xff1a;又称为…...

IO多路转接 —— poll和epoll

文章目录1. poll1.1 poll的函数接口1.2 poll的简单测试程序1.3 poll的优缺点分析2. epoll2.1 epoll的函数接口2.2 epoll的工作原理2.3 epoll的工作模式(LT,ET)2.4 epoll的简易服务器实现(默认是LT工作模式)前言&#xff1a; 接上文讲述的select&#xff0c;它有缺点&#xff0c…...

计算机网络整理-问答

1. 程序工作的时候网络各层的状态 如下图所示&#xff1a; 1. TCP 在进行三次握手的时候&#xff0c;IP 层和 MAC 层对应都有什么操作呢&#xff1f; TCP 三次握手是通过在传输层建立连接的一个过程&#xff0c;在这个过程中&#xff0c;TCP 和 IP 层、MAC 层都起到了重要的…...

JS 实现抛物线动画案例

相信大家都有浏览过&#xff0c;很多购物网站购物车的添加商品动画&#xff0c;今天&#xff0c;我们就手写一个简单的抛物线动画&#xff0c;先上案例&#xff1a; 一、绘制页面 我们这里简单实现&#xff0c;一个按钮&#xff0c;一个购物车图标&#xff0c;样式这里直接跳过…...

CSGO搬砖项目,23年最适合小白的项目!

大家好&#xff0c;我是阿阳 不懂的小伙伴&#xff0c;咱继续听我娓娓道来 steam搬砖主要涉及的是csgo游戏平台装备的一个搬运&#xff0c;比较很好理解&#xff0c;主要就是道具的搬运工&#xff0c;简单来讲就是&#xff0c;从国外steam游戏平台购买装备&#xff0c;再挂到…...

谈谈会话管理

客户端和服务器之间进行数据传输遵循的是HTTP协议, 此协议属于无状态协议(一次请求对应一次响应, 响应完之后断开连接), 服务器是无法跟踪客户端的请求, 通过cookie技术可以给客户端添加一个标识, 客户端之后发出的每次请求都会带着这个标识从而让服务器识别此客户端, 但由于co…...

Linux查看JVM FULL GC频率

查看系统的full gc频率&#xff0c;可以使用jstack命令一、采用top命令定位进程登录服务器&#xff0c;执行top命令&#xff0c;查看CPU占用情况&#xff0c;找到进程的pid二、使用jstack命令统计垃圾回收jstat -gc pid 5000即会每5秒一次显示进程号为pid的java进程的GC情况以上…...

java世界String的那些事

String的创建机理&#xff1a; 由于String在Java世界中使用过于频繁&#xff0c;Java为了避免在一个系统中产生大量的String对象&#xff0c;引入了字符串常量池。其运行机制是&#xff1a;创建一个字符串时&#xff0c;首先检查池中是否有值相同的字符串对象&#xff0c;如果…...

【图像配准】多图配准/不同特征提取算法/匹配器比较测试

前言 本文首先完成之前专栏前置博文未完成的多图配准拼接任务&#xff0c;其次对不同特征提取器/匹配器效率进行进一步实验探究。 各类算法原理简述 看到有博文[1]指出&#xff0c;在速度方面SIFT<SURF<BRISK<FREAK<ORB&#xff0c;在对有较大模糊的图像配准时&…...

2023金三银四季跳槽季,啃完这软件测试面试题,跳槽不就稳稳的了

前言 2023年也到来了&#xff0c;接近我们所说的“金三银四”也正在执行了&#xff0c;时间晃眼就过去了&#xff0c;有的人为了2023跳槽早早做足了准备&#xff0c;有的人在临阵磨刀&#xff0c;想必屏幕前的你也想在2023年涨薪吧&#xff0c;那么问题来了&#xff0c;怎么才…...

【C++详解】——vector类

&#x1f4d6; 前言&#xff1a;本期介绍vector类。 目录&#x1f552; 1. vector的介绍&#x1f552; 2. vector的使用&#x1f558; 2.1 定义&#x1f558; 2.2 iterator&#x1f558; 2.3 空间增长&#x1f558; 2.4 增删查改&#x1f552; 2. vector的模拟实现&#x1f558…...

uniapp 离线本地打包

uniapp打包教程地址 https://nativesupport.dcloud.net.cn/AppDocs/usesdk/android.html点击查看 需要的环境&#xff1a; java (1.8)离线SDK(上面的连接下载即可)Android Studio&#xff08;同上&#xff09; 配置环境变量 依次点击“计算机”&#xff0d;“属性”&#…...

初识马尔科夫模型(Markov Model)

初识马尔科夫模型&#xff08;Markov Model&#xff09;一、概念二、性质三、学习步骤一、概念 马尔科夫模型&#xff08;Markov Model&#xff09;是一种概率模型&#xff0c;用于描述随机系统中随时间变化的概率分布。马尔科夫模型基于马尔科夫假设&#xff0c;即当前状态只…...

KF32A150开发第一步:手把手教你用KF32 IDE导入、编译和烧录第一个工程

KF32A150开发实战&#xff1a;从零完成工程导入到烧录的全流程指南 第一次接触芯旺微KF32系列MCU时&#xff0c;面对陌生的开发环境和工具链&#xff0c;很多开发者都会感到无从下手。本文将带你一步步完成KF32A150开发板的第一个程序烧录&#xff0c;涵盖工程导入、编译配置到…...

让 Claude Code 帮你“看家“:Hooks 与 /loop 入门

让 Claude Code 帮你"看家"&#xff1a;Hooks 与 /loop 入门 上周我把一个重构任务扔给 Claude&#xff0c;出门开了两小时会。回来发现它把 .env.production 改了。 那一刻我才意识到&#xff0c;单纯会用 Claude Code 还不够&#xff0c;你还得学会怎么管住它。折…...

洛谷 P1145:[CERC 1995] 约瑟夫 ← 队列 + 优化

【题目来源】 https://www.luogu.com.cn/problem/P1145 【题目描述】 2k 个人站成一圈&#xff0c;从某个人开始数数&#xff0c;每次数到 m 的人就被杀掉&#xff0c;然后下一个人重新开始数&#xff0c;直到最后只剩一个人。现在有一圈人&#xff0c;k 个好人站在一起&#…...

论人机协同中的模糊性与不确定性

在人工智能从"工具辅助"向"智能伙伴"演进的过程中&#xff0c;人机协同正突破传统"人主导-机执行"的单向模式&#xff0c;形成双向认知交互的新型协作关系。这种关系的复杂性远超简单的人机分工——人类认知的模糊性&#xff08;Fuzziness&#…...

Cherry Studio容器化部署实战指南:从环境搭建到生产运维

Cherry Studio容器化部署实战指南&#xff1a;从环境搭建到生产运维 【免费下载链接】cherry-studio &#x1f352; Cherry Studio is a desktop client that supports for multiple LLM providers. Support deepseek-r1 项目地址: https://gitcode.com/GitHub_Trending/ch/c…...

OpenClaw学习助手:百川2-13B驱动的自动化笔记整理系统

OpenClaw学习助手&#xff1a;百川2-13B驱动的自动化笔记整理系统 1. 为什么需要自动化笔记整理 作为一个经常需要阅读大量技术文档和论文的开发者&#xff0c;我发现自己陷入了一个困境&#xff1a;每次下载新的PDF或PPT文件后&#xff0c;要么没时间仔细阅读&#xff0c;要…...

软件安装包极致压缩与分发加速指南

软件安装包极致压缩与分发加速指南 【免费下载链接】romm A beautiful, powerful, self-hosted rom manager 项目地址: https://gitcode.com/GitHub_Trending/rom/romm 副标题&#xff1a;技术选型全解析 90%效率提升实践 自动化工具包 开发者痛点场景&#xff1a;当…...

NaViL-9B图文对话教程:上传图片即问即答,新手零基础快速上手

NaViL-9B图文对话教程&#xff1a;上传图片即问即答&#xff0c;新手零基础快速上手 1. 认识NaViL-9B&#xff1a;你的智能图文助手 NaViL-9B是一款强大的多模态大语言模型&#xff0c;它能同时理解文字和图片内容。想象一下&#xff0c;你有一个既能聊天又能"看"图…...

风力发电变桨系统避坑指南:从编码器选型到限位开关安装的5个关键细节

风力发电变桨系统避坑指南&#xff1a;从编码器选型到限位开关安装的5个关键细节 在风电行业摸爬滚打多年的工程师们都清楚&#xff0c;变桨系统就像风力发电机组的"神经系统"&#xff0c;任何一个环节的微小失误都可能导致整个系统瘫痪。不同于实验室环境&#xff0…...

智能科学与技术毕设实战:基于Python的AI辅助电影推荐系统设计与避坑指南

最近在帮几个学弟学妹看智能科学与技术专业的毕业设计&#xff0c;发现一个挺普遍的现象&#xff1a;选题听起来高大上&#xff0c;比如“基于深度学习的XX系统”&#xff0c;但真到动手做的时候&#xff0c;从数据获取、模型训练到系统集成&#xff0c;每一步都容易卡壳。最后…...