使用hooks的一些小感想

这里文章说的都是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做比较

有需要做深比较的可以用ahooksuseDeepCompareEffect,用法与 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 (
       

count={count}

); }

大家可能会一直期待着数字的变化,但它就偏不,一直保持着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

仅仅 依赖数据 发生变化, 才会重新计算结果,说是为了性能优化,起到缓存的作用,

这里说一个面试常问的useCallBackuseMemo 有什么区别?

网上各种解析长篇大论的,一句话其实就是

useCallback 缓存钩子函数,useMemo 缓存返回值(计算结果)[当然useMemo也可以传入函数]。

这个时候,有好奇宝贝就会问了,那用这个会多那么多代码量,有什么用呢

答案是:性能优化,这里就要涉及到更深层的react的渲染原理了,"比较更新!!",react每次渲染的时候,它都把值和函数重新计算渲染,这里就会消耗点内存了,用上那2玩意,其实就是告诉react,我们没有变化,帮我存起来,不用再比较了

那么有些姓杠的小朋友,这时候就不耐烦了,站起来问道:为什么react不帮我们自动做这些优化呢,我就想静静地写代码,为什么还要考虑该不该包个useCallBack

问得好,这里顺便@一下官方团队,希望相关单位能密切关注这个问题

还会有些害羞的小朋友会嘀咕着,为什么class组件的时候就不需要注意这些呢

个人鄙见:新旧版本的渲染方法其实差不多的,我觉得前端深入研究性能优化是没有前途的,框架或者浏览器,一次小小的版本更新,可能效果就远远胜过了你多少个日日夜夜的辛勤付出了。

总结

hooks需好,但要小心使用

使用hooks的一些小感想_第1张图片

今天关注公众号,有小哥哥在线指导

本文由博客一文多发平台 OpenWrite 发布!

你可能感兴趣的