自定义hooks
Jul 27, 2022 ·
3 Min Read
自定义的useState ,支持类似class 组件setState 方法
熟悉
this.setState({num: 1}, () => { console.log('updated')})
但是
其实问题也很简单,我们只要对
注:
react hooks 的useState 一定要放到函数组件的最顶层,不能写在ifelse 等条件语句当中,来确保hooks 的执行顺序一致,因为useState 底层采用链表结构实现,有严格的顺序之分。
import { useEffect, useRef, useState } from 'react'
const useXState = (initState) => { const [state, setState] = useState(initState) let isUpdate = useRef() const setXState = (state, cb) => { setState(prev => { isUpdate.current = cb return typeof state === 'function' ? state(prev) : state }) } useEffect(() => { if(isUpdate.current) { isUpdate.current() } })
return [state, setXState] }
export default useXState
实现防抖hooks
useDebounce
接受三个参数,分别为回调函数,时间间隔以及依赖项数组,它暴露了 cancel API
,主要是用来控制何时停止防抖函数用的。
import { useEffect, useRef } from 'react'
const useDebounce = (fn, ms = 30, deps = []) => { let timeout = useRef() useEffect(() => { if (timeout.current) clearTimeout(timeout.current) timeout.current = setTimeout(() => { fn() }, ms) }, deps) const cancel = () => { clearTimeout(timeout.current) timeout = null }
return [cancel] }
export default useDebounce
实现节流hooks
import { useEffect, useRef, useState } from 'react'
const useThrottle = (fn, ms = 30, deps = []) => { let previous = useRef(0) let [time, setTime] = useState(ms) useEffect(() => { let now = Date.now(); if (now - previous.current > time) { fn(); previous.current = now; } }, deps)
const cancel = () => { setTime(0) }
return [cancel] }
export default useThrottle
实现自定义的useScroll
监听一个元素滚动位置
import { useState, useEffect } from 'react'
const useScroll = (scrollRef) => { const [pos, setPos] = useState([0,0])
useEffect(() => { function handleScroll(e){ setPos([scrollRef.current.scrollLeft, scrollRef.current.scrollTop]) } scrollRef.current.addEventListener('scroll', handleScroll, false) return () => { scrollRef.current.removeEventListener('scroll', handleScroll, false) } }, [])
return pos}
export default useScroll
Last edited Feb 15