这里文章说的都是hooksreact
那什么是hooks
故名思义 Hooks
译为钩子,Hooks
就是在函数组件内,负责钩进内部性能的函数。
(说了又如同没说)
有什么爽的
- 函数组件原地飞升
- 不必管this了
- 生命周期也不必记那么多了
开始完结的生命周期能够写在一起,代码更丑陋了
useEffect(()=>{ console.log('开波') return ()=>{ console.log('完结') }},[])// ps.空数组就是只进入一次
props的值的变动,xx值的变动都能放在一起监听
useEffect(()=>{ console.log('无论是数组还是对象,数据多深都能进(起初才发现也不是多深都能啦),这不比vue的watch爽?') // 那么useEffect是怎么监听数据变动的呢 // 它和useLayoutEffect又有什么区别呢 // 这要从hooks的根底概念链表说起,请往下看},[props.a,b])
通过看useEffect的源码,咱们不难发现
// 通过看源码咱们得悉 for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) { if (is(nextDeps[i], prevDeps[i])) { continue; } return false; }// 咱们晓得它的比照办法是// 其中外面的is是这个import is from 'shared/objectIs';function is(x: any, y: any) { return ( (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare );}const objectIs: (x: any, y: any) => boolean = typeof Object.is === 'function' ? Object.is : is;export default objectIs;
所以其实它就是用Object.is
做比拟
有须要做深比拟的能够用ahooks
的useDeepCompareEffect
,用法与 useEffect 统一,但 deps 通过 lodash 的isEqual
进行深比拟。
- 代码复用更高
吐槽一下
闭包陷阱
import {useEffect, useState} from 'react'export default function App() { const [count, setCount] = useState(0) useEffect(()=>{ setInterval(() => { setCount(count + 1) }, 1000); }, []) return ( <p>count={count}</p> );}
大家可能会始终期待着数字的变动,但它就偏不,始终放弃着1
事件为什么会倒退成这样,那就要从底层的渲染开始说起
首次渲染->执行APP->usestate设置count为初始0->1秒后state扭转->视图更新->依照fiber链表执行hooks->useEffect deps 不变->而后1秒后的count始终都是0+1
解决办法:
// 有仔细的网友可能会发现,网上其余中央可能会倡议在useEffect的deps上加上countuseEffect(()=>{ setInterval(() => { setCount(count + 1) }, 1000);}, [count])// 这样的确能拿到最新的count// ❌然而这里喔不倡议这样写// 因为你想想,每次count的更新它都会从新进去建一个新的定时器// 当前画面就会很鬼畜
倡议版本办法
useEffect(()=>{ setInterval(() => { setCount(res=>(res+1)) }, 1000);}, [])// setCount自身能够传办法,原本就是最新的值
高级版本ref大法
//简略来说就是利用useRef返回的是同一个对象,指向同一片内存let ref_ = useRef(1)ref_.current++useEffect(()=>{ setInterval(()=>{ console.log(ref.current) // 3 }, 1000)})
不能用判断或者随机函数
举个
if (Math.random() > 0.5) { useState('first')} let showSex = trueif(showSex){ const [ sex, setSex ] = useState('男'); showSex = false;}
以上的行为都是打咩的
起因是hooks的数据管理是用链表治理的,所以数据不能一时有一时没
举个不太失当的例子,就像
- 数组[0]代表useState('A')
- 数组[1]代表useState('B)
- 当初你忽然把'A'删掉了,那就变成数组[0]代表useState('B')了
- 那么你就不是你了,他也不是他了
useCallBack 还是 useMemo
仅仅 依赖数据
发生变化, 才会从新计算结果,说是为了性能优化,起到缓存的作用,
这里说一个面试常问的useCallBack
和 useMemo
有什么区别?
网上各种解析简明扼要的,一句话其实就是
useCallback 缓存钩子函数,useMemo 缓存返回值(计算结果)[当然useMemo也能够传入函数]。
这个时候,有好奇宝贝就会问了,那用这个会多那么多代码量,有什么用呢
答案是:性能优化,这里就要波及到更深层的react的渲染原理了,"比拟更新!!",react每次渲染的时候,它都把值和函数从新计算渲染,这里就会耗费点内存了,用上那2玩意,其实就是通知react,咱们没有变动,帮我存起来,不必再比拟了
那么有些姓杠的小朋友,这时候就不耐烦了,站起来问道:为什么react不帮咱们主动做这些优化呢,我就想静静地写代码,为什么还要思考该不该包个useCallBack
问得好,这里顺便@一下官网团队,心愿相干单位能亲密关注这个问题
还会有些害羞的小朋友会嘀咕着,为什么class组件的时候就不须要留神这些呢
集体鄙见:新旧版本的渲染办法其实差不多的,我感觉前端深入研究性能优化是没有前途的,框架或者浏览器,一次小小的版本更新,可能成果就远远胜过了你多少个日日夜夜的辛勤付出了。
总结
hooks需好,但要小心应用
<center>明天关注公众号,有小哥哥在线领导</center>
本文由博客一文多发平台 OpenWrite 公布!