这里文章说的都是 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 上加上 count
useEffect(()=>{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 = true
if(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 公布!