i want to trigger countdown of 60 seconds when user click from another component . so far i didn't find any solution
const [seconds, setSeconds] = useState(60)
useEffect(() => {
console.log(state.Trade.length ,"woking in useeffect ");
setInterval(() => {
setSeconds(prevState => prevState - 1)
}, 1000);
}, [state.Trade.length]);
// also use without use effect
const startCounter = () => {
setInterval(() => {
setSeconds(prevState => prevState - 1)
}, 1000);
}
if (state.Trade.length!=0) {
if (seconds==0) return null
startCounter()
}else{
return null
}
it is not working i search a lot but did not find.Thanks
CodePudding user response:
Remember to clear your interval
const [seconds, setSeconds] = useState(60);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds((prevState) => {
if(prevState === 1) clearInterval(intervalId)
return prevState - 1;
});
}, 1000);
}, [state.Trade.length]);
CodePudding user response:
The useEffect
will trigger when state.Trade.length
changes.
You probably need to have a dependency to seconds
.
Something like this:
const [seconds, setSeconds] = useState(60)
useEffect(() => {
console.log(state.Trade.length ,"woking in useeffect ");
setInterval(() => {
setSeconds(prevState => prevState - 1)
}, 1000);
}, [seconds]);
Note that this has 2 issues:
- Linters will complain about not having
state.Trade.length
as dep, but you're just using this to console the value setInterval
just uses the time as a hint. If you want a proper countdown. You should measure the time between 2 invocations and adjust the 1000ms interval.
CodePudding user response:
I can give you some pointer to try based on the question you are asking & the code you have given for reference.
- Dont pass any dependency in the useEffect as it will be executed only when the dependency changes. Keep the dependency array blank then it will work like componentDidMount().
- You can simply use setTimeOut() function to wait for 60 seconds when the component is mounted and then do your logic in that.
- I dont recommend using setSeconds in useEffect when its dependency is seconds variable itself. This might cause an infinite render (as given in one of the answer here).
Edit 1: So what I am doing below is changing the state variable to 1 on a button click to simulate your scenario. Then in one useEffect I am setting an interval to do -1 for the seconds
variable which is 5 here but you can make it 60. On ummount, the interval will be cleared. The second useEffect is just logging when the seconds
changes every second.
const[state,setState]=useState(0)
const[seconds, setSeconds]=useState(5)
useEffect(()=>{
let secondsInterval;
if(state===1){
secondsInterval=setInterval(()=>{
setSeconds(prev=>prev-1)
},1000)
}
return()=>clearInterval(secondsInterval)
},[state])
useEffect(()=>{
console.log("Time remaining: " seconds);
},[seconds])