I'm trying to rerender my component every 5 seconds. The problem occurs when I open the page the first time- it shows after 5 seconds. How should I make sure to make my component visible instantly after page is opened?
useEffect(() => {
const getChargersData = () => {
axios.get(API_URL)
.then(res => {
setChargers(res.data);
})
}
const interval = setInterval(() => {
getChargersData()
},5*1000);
return () => clearInterval(interval);
},[]);
call the getChargerData function before the setInterval, this way the data will be available before the first 5s ellapse
useEffect(() => {
const getChargersData = () => {
axios.get(API_URL)
.then(res => {
setChargers(res.data);
})
}
getChargersData()
const interval = setInterval(() => {
getChargersData()
},5*1000);
return () => clearInterval(interval);
},[]);
Related
I've been trying to call the API every 5 min but the limit for setInterval doesn't allow that.
useEffect(() => {
setInterval(() => {
(() => {
const API_KEY = "C5EQJXXXXXXXXXXXX";
const name = "FB";
axios
.get(
`https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${name}&interval=5min&apikey=${API_KEY}`
)
.then(({ data }) => {
console.log(data);
console.log(data["Time Series (5min)"]);
for (let key in data["Time Series (5min)"]) {
setStocksX((prev) => [...prev, key]);
setStocksY((prev) => [
...prev,
data["Time Series (5min)"][key]["1. open"]
]);
}
//console.log(stocksX, stocksY);
});
})();
}, 30000);
});
Any advice would be appreciated!
Thanks
you can add setInterval with 60 * 5 * 1000 of time, in useEffect hook in first renderization. After you need clear setInterval when unmount component.
const ref = useRef(null)
useEffect(() => {
ref.current = setInterval(yourFunction, 5 * 60 * 1000);
return () => {
if(ref.current){
clearInterval(ref.current)
}
}
}, [])
I wrote this utility hook that I use in my React apps all the time:
import React from 'react';
type IntervalCallback = () => void;
function useDispatch(callback: IntervalCallback, delay: number): void {
const cachedCallback = React.useRef<IntervalCallback>();
React.useEffect(() => {
cachedCallback.current = callback;
}, [callback]);
React.useEffect(() => {
if (delay !== 0) {
const id = setInterval(() => cachedCallback?.current?.(), delay);
return () => clearInterval(id);
}
}, [delay]);
}
export const IntervalHooks = {
useDispatch,
};
I can then use it as such:
IntervalHooks.useDispatch(() => { console.log("hello"); }, 300000);
This gives me a lot of flexibility since I can dynamically update my interval if needed, and takes care of clean up when my component gets unmounted.
I presume that your hook is declaring a new setInterval every 0.5 seconds, possibly making your React App stop in order to avoid memory leak, you just need to declare one setInterval, this means that the second parameter of useEffect should have empty squared brackets
useEffect(() => {
setInterval(yourFunction, 300000); // The function will be called
},[]); // every 5 minutes
onStart is button and when i press it , it must run useeffect but it does not run it in first start but run it on reload. state value change on first start on dev tool.
const [started, setStarted] = useState(false);
const onStart = () => {
setStarted(true);
};
useEffect(() => {
if(started){
let timer = setInterval(() => tick(), 1000);
return () => clearInterval(timer);
}
}, []);
You need to add started to the dependency array of the useEffect.
const [started, setStarted] = useState(false);
const onStart = () => {
setStarted(true);
};
useEffect(() => {
if (started) {
let timer = setInterval(() => tick(), 1000);
return () => clearInterval(timer);
}
}, [started]); // Add started here.
am writing an app in react native and i got a problem with useState and useEffect hooks. I would like to change increment state value by one every 10 seconds.
Here is my code:
const [tripDistance, setTripDistance] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setTripDistance((prevState) => prevState + 1);
console.log(tripDistance);
}, 10000);
return () => {
clearInterval(interval);
};
}, []);
but the output from the console.log is always 0.
What am I doing wrong?
The output is always zero because in your useEffect you are not listening for the changes on tripDistance state. When you call setTripDistance you cannot access the updated value immediately.
You should add another useEffect that listen on tripDistance in order to have the correct console.log.
So you have to do something like:
const [tripDistance, setTripDistance] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setTripDistance((prevState) => prevState + 1);
}, 10000);
return () => {
clearInterval(interval);
};
}, []);
useEffect(() => console.log(tripDistance), [tripDistance]);
try this
const [tripDistance, setTripDistance] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setTripDistance((prevState) => prevState + 1);
}, 10000);
return () => {
clearInterval(interval);
};
}, [tripDistance]);
const HeroSection = () => {
const [Change,setChange] = useState(false);
useEffect(() => {
setInterval(() => {
setChange(!Change)
}, 5000);
return () => clearInterval();
}, [Change]);
return (
<HeroContainer>
<HeroBg>
<ImageBg src={ Change ? Image1 : Image2 } />
</HeroBg>
</HeroContainer>
)``
}
export default HeroSection
react auto slide images works for the first few times then becomes buggy as in fast paced changes of images regardless of the 5 sec interval
clearInterval(); does nothing. You need to pass the created interval's ID to clearInterval for it to be cleared.
I also don't think the effect hook should have change as a dependency unless you use setTimeout instead.
const [change, setChange] = useState(false);
useEffect(() => {
const timeoutId = setTimeout(() => {
setChange(!change)
}, 5000);
return () => clearTimeout(timeoutId);
}, [change]);
to set a new timeout in the effect callback every time change changes.
Or:
const [change, setChange] = useState(false);
useEffect(() => {
const intervalId = setInterval(() => {
setChange(change => !change)
}, 5000);
return () => clearInterval(intervalId);
}, []);
to set an interval only once, when the component mounts.
I have a specific case. The first thing I do is request the Index.DB. After I got the taskId from it, I need to start asking the server every 5 seconds. And stop doing this on a specific flag. How can i do that properly with hooks?
I'tried to use useInterval hook like this:
https://github.com/donavon/use-interval;
But when i set it in useEffect causes consistent error:
Invalid hook call. Hooks can only be called inside of the body of a function component.
const Page = () => {
const [task, setTask] = useState({})
const isLoaded = (task.status === 'fatal');
const getTask = (uuid: string) => {
fetch(`${TASK_REQUEST_URL}${uuid}`)
.then(res => {
return res.json();
})
.then(json => {
setTask(json.status)
})
.catch(error => console.error(error));
};
useEffect(() => {
Storage.get('taskId')
.then(taskId => {
if (!taskId) {
Router.push('/');
}
useInterval(() => getTask(taskId), 5000, isTaskStatusEqualsSomthing)
})
}, []);
return (
<p>view</p>
);
};
I also tried to play around native setInterval like this
useEffect(() => {
Storage.get('taskId')
.then(taskId => {
if (!taskId) {
Router.push('/');
}
setInterval(() => getTask(taskId), 5000)
})
}, []);
But in this case i don't know how to clearInterval and also code looks dirty.
The solution is simple. You just need to configure your setInterval within .then callback like
useEffect(() => {
let timer;
Storage.get('taskId')
.then(taskId => {
if (!taskId) {
Router.push('/');
else {
timer = setInterval(() => getTask(taskId), 5000)
}
}
})
return () => {clearInterval(timer)}
}, []);
The reason, first approach doesn't work for you is because you cannot call a hook conditionally or in useEffect as you did for useInterval