Reputation: 165
I have this component:
export const Widget: FC<IWidgetProps> = ({ appid, flavor, showWidgetField, updateSpeed }) => {
const { state: geocodingState } = useContext(GeocodingContext);
const { dispatch: weatherDispatch } = useContext(WeatherContext);
const fetchCb = useCallback(() => {
if (geocodingState.coords) getWeatherInfo(weatherDispatch)(appid, geocodingState.coords.lon, geocodingState.coords.lat);
}, [geocodingState.coords]);
useEffect(() => {
let interval: NodeJS.Timeout | null = null;
if (!interval) {
interval = setInterval(fetchCb, updateSpeed);
} else {
if (!geocodingState.coords) clearInterval(interval);
}
return () => {
if (interval) clearInterval(interval);
}
}, [geocodingState.coords]);
return (
<>
</>
);
};
Unfortunately, the interval does not get cleared when the geocodingState.coords
is nullified nor in the useEffect return.
Upvotes: 1
Views: 55
Reputation: 2056
Because everytime you change geocodingState.coords, you creating new interval.... and the previous one is still running. Best solution for this is to save interval in useState, because othervise, your code doesnt know ID of interval, that needs to be cleared.
export const Widget: FC<IWidgetProps> = ({ appid, flavor, showWidgetField, updateSpeed }) => {
const { state: geocodingState } = useContext(GeocodingContext);
const { dispatch: weatherDispatch } = useContext(WeatherContext);
const [intervalId, setIntervalId] = useState();
const fetchCb = useCallback(() => {
if (geocodingState.coords) getWeatherInfo(weatherDispatch)(appid, geocodingState.coords.lon, geocodingState.coords.lat);
}, [geocodingState.coords]);
useEffect(() => {
if (!intervalId) {
interval = setInterval(fetchCb, updateSpeed);
setIntervalId(interval)
} else {
if (!geocodingState.coords) clearInterval(intervalId);
}
return () => {
if (intervalId){
clearInterval(interval);
setIntervalId(undefined);
}
}, [geocodingState.coords]);
return (
<>
</>
);
};
Upvotes: 1