记一次hooks陷阱
今天写一个hook,正想发挥hooks这种高级复用方式来缩短我的开发时间,就出现了一个新bug。
我编写的这个hook用于管理数据列表状态。除了导出内部的状态外,还导出一些方法供外部调用。代码简化如下:
function useDataList() {
const [rows, setRows] = useState([])
const [pageIndex, setPageIndex] = useState(0)
async function loadNextPage() {
const res = await api.searchData(pageIndex+1)
setRows(res.data.rows)
setPageIndex(index+1)
}
return {
rows,
setPageIndex,
nextPage
}
}
然后这样使用这个hook:
function App() {
const {rows, setPageIndex, loadNextPage} = useDataList()
useEffect(()=>{
setPageIndex(-1) // 因为loadNextPage中会给pageIndex加一,而初始我们希望请求第0页,因此设为-1
// 因为setPageIndex()不会立刻改变pageIndex,因此要在下一个事件循环调用loadNextPage()
setTimeout(()=>{
loadNextPage()
})
}, [])
return (
{/* 这里使用rows渲染列表 */}
)
}
好,现在问题出现了。api.searchData()请求的是第1页,而不是第0页,你知道为什么吗?
原因就在于产生了闭包。
useEffect在App第一次渲染的时候执行,以后不再执行。
这时loadNextPage指向的是第一次App()指向时的loadNextPage,
而这个loadNextPage是第一次执行useDataList时导出的,
它内部的pageIndex保存的是第一次执行useDataList()时的pageIndex的值,也就是0。
因此调用loadNextPage()时,请求的页码是pageIndex+1=0+1=1。
我这种情况和网上说的hooks陷阱有点不一样,但是原理是一样的,都是闭包问题。
查阅资料发现,可以使用ahooks的useMemorizedFn解决这个问题。
这个API可以保持传入的函数不变,但是每次函数执行时访问的都是最新的state。
于是代码这样改:
function App() {
const {rows, setPageIndex, loadNextPage} = useDataList()
const wrapedLoadNextPage = useMemorized(()=>{
loadNextPage()
})
useEffect(()=>{
setPageIndex(-1)
setTimeout(()=>{
wrapedLoadNextPage()
})
}, [])
return (
{/* 这里使用rows渲染列表 */}
)
}
最后感叹一下,原本以为新技术哪有什么难的,只要迁移以前的知识就行了呗。
结果发现,同一个功能点,用不同的技术实现就是有差别,新的技术产生新的问题,从而导致项目延期。
比如会使用vue开发网页,使用rn开发APP问题应该不大,结果rn的语法和vue不同。
又比如使用uniapp开发过小程序,那使用rn开发APP应该会挺快,结果RN的生态真的简陋,没有uniapp那么齐全方便。
再比如hooks解决了class组件复用上的一些问题,那用起来应该很顺手,结果出了今天的hooks陷阱的问题。
...
下一次学习新技术,要谨慎。
记一次hooks陷阱的更多相关文章
- 4.Shell内部命令
4.Shell内部命令内部命令是由shell自身提供的.如果某个内部命令的名称是一个简单命令的第一个单词,shell会直接执行这个命令,而不会启动其它程序.对于一些不可能或者不方便通过外部程序实现的功 ...
- React躬行记(15)——React Hooks
Hook(钩子)是React v16.8新引入的特性,能以钩子的形式为函数组件附加类组件的状态.生命周期等特性.React的类组件有难以拆分.测试,状态逻辑分散,难以复用等问题,虽然可以通过渲染属性( ...
- 记jQuery.fn.show的一次踩坑和问题排查
最近很少已经很少用jQuery,因为主攻移动端,常用Zepto,其实很多细节和jQuery并不一样.最近又无意中接触到了PC的需求和IE6, 使用了jQuery,刚好踩坑了,特意记录一下. 本文内容如 ...
- [转]AngularJS: 使用Scope时的6个陷阱
在使用AngularJS中的scope时,会有6个主要陷阱.如果你理解AngularJS背后的概念的话,这6个点其实非常的简单.但是在具体讲述这6个陷阱之前我们先要讲两个其它的概念. 概念1: 双向数 ...
- SQL Server AlwaysON 同步模式的疑似陷阱
原文:SQL Server AlwaysON 同步模式的疑似陷阱 SQL Server 2012 推出的最重要的功能之一Alwayson,是一个集之前Cluster和Mirror于一体的新功能,即解决 ...
- shell中while循环的陷阱
在写while循环的时候,发现了一个问题,在while循环内部对变量赋值.定义变量.数组定义等等环境,在循环外面失效. 一个简单的测试脚本如下: #!/bin/bash echo "abc ...
- 精通Web Analytics 2.0 (12) 第十章:针对潜在的网站分析陷阱的最佳解决方案
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第十章:针对潜在的网站分析陷阱的最佳解决方案 是时候去处理网站分析中最棘手的一些问题了,然后获得属于你的黑带,这是成为分析忍者的 ...
- SVN Hooks的介绍及使用
阅读此篇文章你可以: 对SVN Hooks有一定的了解 获取两个最常用的SVN Hooks案例 SVN hooks介绍 Hooks 钩子,主要实现的功能就是在特定事件发生之前或者之后自动执行事先定义好 ...
- Linux History安全问题【保存记录防止删除】+完善Linux/UNIX审计 将每个shell命令记入日志
2011-09-27 22:11:51| 分类: rhel5_033|举报|字号 订阅 Linux利用PROMPT_COMMAND实现审计功能 这个系统审计,记录什么用户,在什么时间,做 ...
- CTSC2018 & APIO2018 颓废 + 打铁记
CTSC2018 & APIO2018 颓废 + 打铁记 CTSC 5 月 6 日 完美错过报道,到酒店领了房卡放完行李后直接奔向八十中拿胸牌.饭票和资料.试机时是九省联考的题,从来没做过,我 ...
随机推荐
- Windows上将linux目录映射网络驱动器
我有两台PC,一台操作用的Windows,一台linux.为了方便对linux目录的文件操作.需要在Windows上将linux中的/fdsk目录映射为网络驱动器. a.首先要将linux安装成为sa ...
- 第三章 --------------------XAML的属性和事件
1.XAML注释是什么样子的? 在之前的章节有提起过,但是这一节我还是想系统的学习XAML,XAML的注释如下 <!-- //这其中填写注释 --> Notice:在注释的部分编译器是不编 ...
- Centos7下vim最新版本安装
一直以来用的都是vim,因为之前都是系统自带的vim没有研究过怎么自己安装,今天趁着刚装完新系统,顺便装下vim. 同样vim也有两种安装方法: 一.yum安装,centos下安装软件最简单的方法了, ...
- [cocos2d-x]关于CC_CALLBACK
CC_CALLBACK的代码 // new callbacks based on C++11 #define CC_CALLBACK_0(__selector__,__target__, ...) s ...
- webpack动态配置多静态资源路径,动态配置多上线路径,配置less,多种图片引用方式----"webpack": "^4.41.6",
1.项目场景是有两个静态资源目录,一个用于开发,一个用于发布,上线多个版本,打包多个版本后,也要部署到同一个服务器的同一个端口下. 根据我自己的摸索,我搞出来了下面的配置,自感觉还蛮好用的 先看我的c ...
- SEO关键词布局方法
关键词在<title>标签. description属性. keywords属性中是如何布局的. 1.<title>标签中布局关键词 <title>标签是用来定义网 ...
- Unity跑在Awake之前的方法
Unity跑在Awake之前的方法 一.前言 相信大家和小黑一样,在写项目的时候遇到过以下这中情况: ____两个脚本的Awake中,都有获取信息的函数被调用.可是A脚本在B脚本获取到信息之后,才可以 ...
- 【学习笔记】XR872 Audio 驱动框架分析
Xradio Sdk 的 Audio 驱动框架和 Linux 的 ASOC 驱动框架非常相似,只不过简化了很多. 驱动和芯片之间的关系图 下面的 SOC 表示的是 XR872 芯片,这里以 AC107 ...
- 11月17日内容总结——黏包现象、struct模块和解决黏包问题的流程、UDP协议、并发编程理论、多道程序设计技术及进程理论
目录 一.黏包现象 什么是黏包 黏包现象产生的原因 二.struct模块及解决黏包问题的流程 struct模块 解决黏包问题初级版本 解决过程中遇到的问题 解决黏包问题终极解决方案 三.粘包代码实战 ...
- Selenium4.6版本浏览器自动退出问题
Selenium4.6版本浏览器自动退出问题 代码 from selenium import webdriver driver = webdriver.Chrome() driver.get('htt ...