React useCallback linting错误缺少依赖项



我在组件中使用自定义挂钩useInstantSearch

当我把它包装在useCallback中时,我得到以下错误:

React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead.

这是代码:

const [searchTerm, setSearchTerm] = useState<string>(searchQuery);
const handleDebouncedSearch = useCallback(
useInstantSearch(searchTerm, (search, cancelTrigger, searchStillValid) => {
console.log('instant search', search);
}),
[]
);
useEffect((): void => {
handleDebouncedSearch(searchTerm);
}, [searchTerm, handleDebouncedSearch]);

因此,有效地将更新后的搜索词发送到子组件以供显示,然后当该词发生变化时,父组件将处理搜索的取消抖动。

search, cancelTrigger, searchStillValid

不是父组件的一部分,而是useInstantSearch的一部分。

这是我可以忽略的警告吗?

import { useEffect, useRef } from 'react';
import { CancelTrigger } from '../../../ars/api/api.cancel';
const DELAY_SEARCH_MS = 300;
interface InstantSearchOnChange {
(search: string, cancelTrigger: CancelTrigger, resultStillValid: { (): boolean }): void;
}
/**
* Helper to delay request until user stop typing (300ms), support deprecated requests (cancel and helper to not update the state), or unmounted component.
*/
export default function useInstantSearch(initialSearch: string, onChange: InstantSearchOnChange): { (value: string): void } {

const search = useRef<string>(initialSearch);
const requests = useRef<CancelTrigger[]>([]);
const mounted = useRef<boolean>(true);
useEffect(() => {
return (): void => {
mounted.current = false;
};
}, []);
return value => {
search.current = value;
setTimeout(() => {
if (search.current === value) {
requests.current = requests.current.filter(r => !r.cancel());
const trigger = new CancelTrigger();
requests.current.push(trigger);
onChange(value, trigger, () => search.current === value && mounted.current);
}
}, DELAY_SEARCH_MS);
};
}

由于您使用的是一些外部函数,您可以简单地忽略以下消息:

useCallback(
useInstantSearch(...)
, []) // eslint-disable-line react-hooks/exhaustive-deps

然而,您应该像使用一样使用它

const [searchTerm, setSearchTerm] = useState<string>(searchQuery);
const handleDebouncedSearch = useCallback(() => { // -> this
useInstantSearch(searchTerm, (search, cancelTrigger, searchStillValid) => {
console.log('instant search', search);
})
}, [searchTerm]); // eslint-disable-line react-hooks/exhaustive-deps

这里需要Eslint注释,因为您在useInstantSearch中使用回调,因为无法将它们作为依赖项注入。

如果你不介意过时的闭包,你可以忽略它——你可以这样做:

const { useRef, useCallback, useEffect } = React;
const DELAY_SEARCH_MS = 300;
const later = (value, time) =>
new Promise((resolve) =>
setTimeout(() => resolve(value), time)
);
/**
* Helper to delay request until user stop typing (300ms), support deprecated requests (cancel and helper to not update the state), or unmounted component.
*/
function useInstantSearch(onChange) {
const timeout = useRef();
const mounted = useRef(true);
useEffect(() => {
return () => {
mounted.current = false;
};
}, []);
return useCallback(
(value) => {
clearTimeout(timeout.current); //cancel other
timeout.current = setTimeout(() => {
const current = timeout.current;
onChange(
value,
() =>
//comparing timeout.current with current
//  async function may not be the last to resolve
//  this is important when you want to set state based
//  on an async result that is triggered on user input
//  user types "a" and then "b" if 2 async searches start
//  "a" and "ab" and "a" is so slow it will resolve after "ab"
//  then state result will be set for "ab" first and then with "a"
//  causing UI to be out of sync because user searched for "ab"
//  but results for "a" are shown
timeout.current === current && mounted.current
);
}, DELAY_SEARCH_MS);
},
[onChange]
);
}
const App = () => {
const handler1 = useCallback(
(value) => console.log('handler1:', value),
[]
);
const handler2 = useCallback(
(value) => console.log('handler2:', value),
[]
);
const handler3 = useCallback((value, shouldResolve) => {
console.log('starting async with:', value);
return later(
value,
value.length === 1 ? 1000 : 800
).then(
(resolve) =>
shouldResolve() &&//you can opt not to set state here
console.log('resolved with', resolve)
);
}, []);
const debounced1 = useInstantSearch(handler1);
const debounced2 = useInstantSearch(handler2);
const debounced3 = useInstantSearch(handler3);
[1, 2, 3].forEach(
(num) =>
setTimeout(() => {
debounced1(num);
debounced2(num * 2);
}, 100) //lower than the 300 of debounce
);
//both callbacks will be called but "a" resolves after "ab" since
//  "ab" was the last to be requested it will be the only one that logs
//  resolved with
setTimeout(() => debounced3('a'), 500);
setTimeout(() => debounced3('ab'), 1500);
return 'hello world (check console)';
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

你的问题可能有解决方案,但如果不知道useInstantSearch是什么,就不可能提供解决方案。

我的猜测是,您应该在useInstantSearch中使用useCallback,但由于您的问题中缺少该代码,我只能猜测。

相关内容

  • 没有找到相关文章

最新更新