Skip to content

常用的React Hooks

Hooks

  • 由于函数组件没有this,为了能够处理组件内部的状态以及副作用,提供了 Hooks 的方式
  • 自定义Hooks可以便于组件逻辑的封装和复用,相比于HOC的使用更加方便和高效
  • 常见的Hooks
    • useState
      • 存储组件内部状态,接收一个初始化的值后除非调用setState,否则state的值不会改变
      • setState的参数可以为newState,也可以是一个函数,参数为oldState,返回值为newState
    • useEffect
      • 处理副作用的函数,接收两个参数,第一个参数为一个函数fn,第二个参数为监听变化的state数组
      • 执行函数fn可以返回一个清理函数,在每次组件渲染完成之后都会调用该清理函数
      • 依赖的state数组不传时,每次组件渲染都会执行函数fn
      • 依赖的state数组传空数组时,只会在组件初次渲染时执行一次fn
      • 当出现循环渲染时,需要考虑将循环的依赖替换为ref或者使用 useEffectEvent hook
    • useLayoutEffect
      • 与useEffect用法类似,但是内部的执行函数为同步执行,会阻塞浏览器渲染
      • 它在SSR中无效,只能在客户端使用
    • useCallback
      • 用于缓存组件内的函数以提升性能,接收两个参数,第一个为要执行的函数,第二个为函数的依赖
      • 与useEffect不同,该hook用于声明函数,需要在使用的时候手动调用执行
    • useMemo
      • 与useCallback类似,可以用来缓存基本的数据类型
      • 若用来缓存函数,则跟useCallback效果一样
    • useContext
      • 用于读取和订阅组件中的context,通常与createContext搭配使用
    • useReducer
      • 根据Redux来的状态管理hook,接收两个参数,第一个为reducer,第二个为默认的state
      • 返回一个数组,可解构为[state, dispatch],state为当前的状态值,dispatch用于触发状态更新
      • 与 useContext 搭配可以实现跟 Redux 一样效果
    • useRef
      • 用于创建一个不触发渲染的值,值的更新和删除都不会触发组件渲染,且在组件每次渲染的context中都能获取到最新值
    • useImperativeHandle
      • 用于向父组件暴露出 ref,便于在父组件中直接调用子组件方法,需要搭配 forwardRef API使用(react19不需要)
      • 接收三个参数,第一个为forwardRef中的ref,第二个为一个函数,返回的对象为父组件中ref获取到的对象,第三个参数为可选的依赖数组

useCallback

会返回一个被缓存的函数。

  1. 优化性能:如果一个函数作为子组件的props。每次渲染的时候,这个函数都会是新函数。那么props就会是新的。那么子组件永远都会重新渲染。就算子组件使用memo都无法避免。
  2. 避免不必要的计算:如果函数内部有昂贵的计算,可以避免重新计算。
  3. 如果函数作为某个hook的依赖,使用useCallback避免重复触发这个hook。如防止频繁触发useEffect。 如果useCallback没有依赖,将不生效。

useMemo

返回一个缓存的值

  1. 当一个函数计算成本比较高,避免重复计算(一般来说除非遍历上千对象,否则开销并不大)
  2. 当这个值是一个对象或数组,且是另一个子组件的props的时候,可以避免子组件每次都重新渲染。
  3. 当这个值是对象的时候,是另一个hook的依赖的时候,可以避免重复触发hook。
  4. 也可以记忆一个函数,和useCallback 类似。

useId

为了解决SSR中id生成的问题,之前我们可能使用uuid或随机数生成id,但是在ssr中,服务端和客户端生成的id不一样。

useLayoutEffect

可能影响性能,在浏览器重新绘制屏幕之前触发。可以进行dom操作,比如获取dom位置,防止用户看见闪烁。

useContext

结合CreateContext、Provide进行使用,用于向组件树深层传递数据。

useImperativeHandle

结合使用forwardRef,用于向父组件暴露ref。比如暴露方法,父组件可以调用子组件的方法。

useDeferredValue vs useTransition

useDeferredValue 可以延迟更新页面的内容,通过延迟更新state。 let v = useDeferredValue(state)

useTransition 可以在不阻塞UI的情况下更新React Hook。通过调用setState。 useTransition(() => setState)

useSyncExternalStore

可以订阅外部store,浏览器API

第一个参数是一个函数,函数内部做订阅逻辑,并return取消订阅

第二个参数是也是一个函数,return订阅的值。

let isOnLine = useSyncExternalStore(subscript, getSnapshot)