Implementation principles of 3 custom anti-shake Hooks

Foreword—

This article introduces the idea and implementation of customizing Hooks in the daily development process by implementing three kinds of custom anti-shake Hooks, useDebounceFn, useDebounce, and useDebounceEffect, and helps everyone complete general Hooks to improve development efficiency.

Stabilization—

The concept of anti-shake is commonplace, here is a brief introduction:

  • Example: input event, originally inputting 10 characters continuously will trigger 10 events, but using anti-shake can only trigger one event when inputting intermittently

  • Anti-shake: A continuous event can be defined by anti-shake as an event that exceeds a specified time to trigger

A simple anti-shake can be achieved by closure + timer:

function debounce(fn, delay) {
  let timer = null

  return function (...args) {
    // 下一次触发时清空定时器,这样事件就要等新的定时器结束后才执行了
    if (timer) {
      clearTimeout(timer)
    }

    timer = setTimeout(() => {
      fn.call(this, ...args)
    }, delay)
  }
}

Debounce inside React function components —

real scene

For example, one such requirement is to search for data when updating the Input input box.

A similar function diagram is as follows:

Through React useEffect, a simple demo is implemented as follows:

import { Input } from 'antd'
import { useEffect, useState } from 'react'
import './App.css'

function App() {
  const [val, setVal] = useState('')

  const onSearch = (val) => {
    console.log('搜索', val || '全部')
  }

  const onChange = (e) => setVal(e.target.value)

  // 当 val 发生变化时,请求搜索数据
  useEffect(() => {
    onSearch(val)
  }, [val])

  return (
    <div className='App'>
      <Input value={val} placeholder='请输入' onChange={onChange} allowClear />
    </div>
  )
}

At this time, you can see that when you enter the page for the first time, you will initiate two requests to query all the search data, and then each time the input box is updated, you will initiate a request for search data.

Normally, if we add debounce to the onSearch event, we can initiate a search data request after the input operation pauses for a specified time.

What needs to be noted here is to add useCallback to avoid repeated triggering of delayed events caused by repeated rendering.

After encapsulating the onSearch method with debounce + useCallback, the anti-shake effect can be achieved.

const onSearch = useCallback(
  debounce((val) => {
    console.log('搜索', val || '全部')
  }, 500),
  []
)

The next step is to package the anti-shake logic into different custom Hooks according to three different ideas.

useDebounceFn

The idea of ​​the first custom anti-shake Hooks is to encapsulate the above debounce + useCallback into a general custom Hooks useDebounceFn to implement a function with anti-shake effect.

How to use: useDebounceFn(fn1, options).

interface DebounceOptions {
  wait?: number;
}

const useDebounceFn = (fn: (...args: any) => any, options: DebounceOptions) => {
  return useCallback(debounce(fn, options.wait), [])
}

const onSearch = useDebounceFn(
  (val) => {
    console.log('搜索', val || '全部')
  },
  {
    wait: 500,
  }
)

useDebounce

The idea of ​​the second custom anti-shake Hooks is to create a new state, setState is encapsulated with useDebounceFn, and returns a state with anti-shake effect.

How to use: useDebounce(state, options).

function useDebounce<T>(value: T, options: DebounceOptions) {
  const [debounced, setDebounced] = useState(value)

  const update = useDebounceFn((value) => {
    setDebounced(value)
  }, options)

  useEffect(() => {
    update(value)
  }, [value])

  return debounced
}

Changing the dependency of useEffect to the state returned by useDebounce can also achieve search stabilization:

const debounceVal = useDebounce(val, { wait: 500 })
const onSearch = (val: string) => {
  console.log('搜索', val || '全部')
}

// 当 debounceVal 发生变化时,请求搜索数据
useEffect(() => {
  onSearch(debounceVal)
}, [debounceVal])

useDebounceEffect

The idea of ​​the third custom anti-shake Hooks is to create a new state, setState is encapsulated with useDebounceFn, and the anti-shake update state is updated when the dependency is updated, and the side effect is executed when the new state is updated. useEffect for the effect.

How to use: useDebounceEffect(effect, deps, options).

function useDebounceEffect(
  effect: EffectCallback,
  deps: DependencyList,
  options: DebounceOptions
) {
  const [debounced, setDebounced] = useState({})

  const update = useDebounceFn(() => {
    setDebounced({})
  }, options)

  useEffect(() => {
    update()
  }, deps)

  useEffect(effect, [debounced])
}

Change useEffect to useDebounceEffect to achieve search anti-shake:

useDebounceEffect(
    () => {
      onSearch(val)
    }
    [val],
    { wait: 500 }
  )

summary-

You should be clear about the implementation idea of ​​custom anti-shake Hooks. You can use this idea to encapsulate the general logic in your components into general Hooks.

The useDebounceFn, useDebounce, and useDebounceEffect three anti-shake Hooks implemented in this article can be directly downloaded from ahooks[1] for use.

References—

[1]

ahooks: https://ahooks.js.org/zh-CN/hooks/use-debounce

Guess you like

Origin blog.csdn.net/crg18438610577/article/details/130126051