使用反应钩子去抖动或节流

时间:2021-06-01 17:18:41

标签: reactjs react-hooks throttling

当来自输入字段的搜索查询参数发生更改时,我需要发出 api 请求,但前提是该字段不为空。

我正在使用在此站点上找到的几个答案进行测试,但无法使它们正常工作

首先this一个带有自定义钩子的

export function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
}

现在在我的组件中我这样做

const debouncedTest = useDebounce(() => {console.log("something")}, 1000);

但这似乎在每次重新渲染时都会调用,而不管任何参数,我需要能够在 useEffect 中调用它,就像这样

useEffect(() => {
  if (query) {      
    useDebounce(() => {console.log("something")}, 1000);
  } else {
    //...
  }
}, [query]);

这当然行不通

另一种使用 lodash 的方法

const throttledTest = useRef(throttle(() => {
  console.log("test");   
}, 1000, {leading: false}))

但是我如何从上面的 useEffect 触发这个?我不明白如何进行这项工作

谢谢

2 个答案:

答案 0 :(得分:1)

你的钩子的签名和你调用它的时候不一样。

也许您应该按照以下方式做一些事情:

const [state, setState] = useState(''); // name it whatever makes sense
const debouncedState = useDebounce(state, 1000);

useEffect(() => {
  if (debouncedState) functionCall(debouncedState);
}, [debouncedState])

答案 1 :(得分:0)

我可以在这里快速指出一两件事。

useEffect(() => {
  if (query) {      
    useDebounce(() => {console.log("something")}, 1000);
  } else {
    //...
  }
}, [query]);

从技术上讲,您不能执行上述操作,useEffect 不能嵌套。

通常 debounce 与钩子没有任何关系。因为它是一个普通的函数。因此,您应该首先寻找可靠的去抖动,创建一个或使用 lodash.debounce。然后构造您的代码以调用 debounce(fn)Fn 是您要延迟的原始函数。

此外,debounce 也适用于经常变化的情况,这就是您想要应用去抖动来降低频率的原因。因此,在 useEffect 中看到它的情况相对少见。

  const debounced = debounce(fn, ...)
  const App = () => {
    const onClick = () => { debounced() }
    return <button onClick={onClick} />
  }

还有一个常见问题,人们可能会在 App 中使用 debounce 功能。这也不正确,因为每次呈现时都会触发 App

我可以稍后提供一个相对更详细的解决方案。如果您也能解释一下您想做什么,这会有所帮助。