React Custom hook 踩坑日记 - useDebounce

今天要分享的是我们在优化前端时常会做的处理,Debounce & Throttle,那关于这两个名词的解释,网路上有很多专门在讲解的文章,也可以参考连结。

所以,以实现这样的功能来说我们会需要一个setTimeout来当作阻挡的中继器,我们可以用custom hook的概念做组建的拆分,用来实践两种不同情境的功能。

首先,我们先试者製作useTimeout的custom hook:

import { useCallback, useEffect, useRef } from "react";const useTimout = (callback, delay) => {  const callbackRef = useRef(callback)  const timeoutRef = useRef()  // 透过 ref change 条件触发更新事件  useEffect(() => {    callbackRef.current = callback  }, [callback])  // 透过 useCallback 减少重複 setTimeout   const set = useCallback(() => {    timeoutRef.current = setTimeout(() => callbackRef.current(), delay)  }, [delay])  const clear = useCallback(() => {    timeoutRef.current && clearTimeout(timeoutRef.current)  }, [])  // 这里是主要的作用 hook 主要做值更改的部分,在更动完后清除timeout  useEffect(() => {    set()    return clear  }, [delay, set, clear])  const reset = useCallback(() => {    clear()    set()  }, [clear, set])  // 如果不用 clear, reset function 也可以不定义  return { clear, reset }}export default useTimout;

这个hook就是一个计时器功能的作用,有clear & reset两个function可以做调整,使用範例:

// ...省略import useTimeout的做法const exampleComponent = () => {  const [count, setCount] = useState(0)  const {clear, reset} = useTimeout(() => setCount(10), 1000)      return (    <div>      <h1>useTimout</h1>      <p>{count}</p>      <Button p={`1rem`} onClick={() => setCount(prev => prev + 1)}>++</Button>      <Button p={`1rem`} onClick={clear}>clear</Button>      <Button p={`1rem`} onClick={reset}>reset</Button>    </div>  )}

跑起来后会在一秒之后自动执行() => setCount(10)的function, 也可以当倒数计时器使用。

接着我们照这debounce的执行逻辑去製作useDebounce的custom hook:

import { useEffect } from "react"import useTimout from "./useTimeout"// 等待动作停止后,触发其他function,适合用于query apiconst useDebounce = (callback, delay, dependencies) => {  // 这边直接将动作和delay时间带入useTimeout  const { reset, clear } = useTimout(callback, delay)  // dependencies是整个array, 当然你可以只带入里面的值  // 这里是透过reset重新计时  useEffect(reset, [...dependencies, reset])  // 这里不希望一开始就触发callback,所以加了一个clear  useEffect(clear, [])}export default useDebounce;

使用範例如下:

// ...省略import hooksconst exampleComponent = () => {  const [count, setCount] = useState(0)  // 这里的alert只是示範,实务上可以改成其他动作的function  useDebounce(() => alert(count), 1000, [count])      return (    <div>      <h1>useDebounce</h1>      <p>{count}</p>      <Button p={`1rem`} onClick={() => setCount(prev => prev + 1)}>++</Button>    </div>  )}

设想一下这类的功能如果放在原本searchbar input的功能栏位,可以有效降低不必要的query,所以在实际应用上是很常见的功能。

那么,以上的範例就是这一篇的分享,Throttle的部分就让你们自己练习吧!

基本上逻辑是差不多的,这系列的更新可能就到这篇吧,因为有太多第三方的套件已经整合好这类custom hook的function,这也是为什么那么久没更新了,最近转而使用typescript在专案上,像usehook或是mantine这类的套件,能大幅降低自己写custom hook的时间,而且有团队维护应该还是比较省事的做法,一样推荐给各位,希望还是有帮助到大家!


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章