使用函数作为参数的自定义React钩子

时间:2019-11-21 11:01:53

标签: reactjs react-hooks

我正在尝试编写自定义钩子,但是每当我想将函数用作参数时,我都会遇到一个问题。

我想写一个useDebouce钩子;从网络上的示例中,我得出以下结论:

async (ctx, next) => {
    ctx.set('Set-Cookie','name=fromBackEnd;max-age=303003030;Domain=http://localhost:8080;path=/');
    ctx.response.type = 'application/json';
    ctx.response.body = await query.menu({where: {...tool.parseUrl(ctx.request.url), flag: 0}})
}

无论何时更改参数,我都想重置。

但是,如果我这样使用它:

import { useCallback, useEffect } from 'react';
import debounce from 'lodash/debounce';

const useDebounce = (fn, time, options) => {
  useEffect(() => console.log('reset'), [fn, time, options]);
  return useCallback(debounce(fn, time, options), [fn, time, options]);
};

每次我的组件呈现函数和对象引用更改(第一个和第三个参数)时,这意味着我最终每次都会创建一个新的去抖动的函数。 因此,防抖行为不起作用。

处理每次渲染时更改的回调引用的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

没有出路,用户必须确保它具有相同的引用:

import { useCallback, useEffect } from 'react';
import debounce from 'lodash/debounce';

const useDebounce = (fn, time, options) => {
  useEffect(() => {
    // Don't forget to cancel the debounce
    return () => debounce(fn).cancel();
  }, [fn, time, options]);

  return useCallback(debounce(fn, time, options), [fn, time, options]);
};

const log = () => console.log('test');
const maxWait = { maxWait: 1000 };

// Outer scope holds the same reference
const randomComponent = () => {
  const doSomething = useDebounce(log, 500, maxWait);
};

// Or memoization, more usefull with state
const randomComponent = () => {
  const log = useCallback(() => console.log('test'), []);
  const maxWait = useMemo(() => ({ maxWait: 1000 }), []);
  const doSomething = useDebounce(log, 500, maxWait);
};

此外,如果您不想处理引用,则用户可以提供比较功能。可能建议尝试另一种方法:

// Something like that (not tested)
const useDebounce = (fn, time, options, comp) => {
  const debounceRef = useRef(debounce(fn, time, options));

  if (comp(fn, time, options)) {
    debounce(debounceRef.current).cancel();
    debounceRef.current = debounce(fn, time, options);
  }

  return useCallback(debounceRef.current, []);
};