Вот useInterval, который я придумал
function (callback, options, cleanup) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (options.delay !== null) {
let id = setInterval(tick, options.delay);
return () => {
clearInterval(id);
cleanup && cleanup();
}
}
return () => cleanup && cleanup();
}, [options]);
}
И я использую его так
const [fetchOptions, setFetchOptions] = useState({delay: 5000, id: 'someid'});
let ignore = false;
useInterval(
() => {
fetchData(fetchOptions.id).then(data => {
if (!ignore) {
setData(data);
}
});
},
fetchOptions,
() => (ignore = true),
);
Я не уверен, есть ли лучший способ написать это. Меня беспокоит то, что переменная ignore
находится в контексте функции / компонента. В примере кода вопроса, переменная ignore находится внутри useEffect и чувствует себя чище.
Недостатком этого подхода является то, что fetchOptions должна быть переменной useState, иначе она будет сбрасывать ловушку useInterval при каждом рендеринге, еслиэто была просто константа в функции.