I'm trying to build pomodoro clock (25 5).
I have an arrow function in the child component which takes two variabels: session (passed from parent, in seconds) and Boolean var. Problem is the function always stays at 1500 seconds even after i modified session in the parent component. It still passing the updated variable in the child but function always shows 25mins, cant find what am i doing wrong here.
The countdown itself works fine, i just need to figure out how to change amount of time passed in that function (called Countdown in the child component)
Child component:
import React, {useState, useEffect} from "react";
const Countdown = (Session, isStarted) => { // In this function Session is always 25 mins even after if i modify the state of the variable in the parent
let InitialMinutes = Math.floor(Session / 60);
let InitialSeconds = Session % 60;
const [minutes, setMinutes ] = useState(InitialMinutes);
const [seconds, setSeconds ] = useState(InitialSeconds);
useEffect(()=>{
if (isStarted) {
let myInterval = setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(myInterval)
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000)
return ()=> {
clearInterval(myInterval);
};
}}, [minutes, seconds, isStarted]);
return (
<div>
{ minutes === 0 && seconds === 0
? null
: <h1> {minutes}:{seconds < 10 ? `0${seconds}` : seconds}</h1>
}
</div>
)
}
function Timer({session}) {
const [isStarted, setIsStarted] = React.useState(false);
return (
<div className='timer'>
<h3>Session</h3>
{Countdown(session, isStarted)}
<button onClick={() => setIsStarted(true)}>start</button>
<button>stop</button>
<button>{session}</button>
</div>
)
}
export default Timer
Parent component:
function App() {
const [Break, setBreak] = React.useState(5);
const [Session, setSession] = React.useState(1500);
const increaseBreak = () => {
setBreak(prevBreak => prevBreak 1);
};
const decreaseBreak = () => {
if (Break === 5) return Break
setBreak(prevBreak => prevBreak - 1);
};
const increaseSession = () => {
setSession(prevSession => prevSession 60);
console.log(Session)
}
const decreaseSession = () => {
return Session === 300? Session : setSession(prevSession => prevSession - 60);
}
const formatTime = time => {
let minutes = Math.floor(time / 60);
let seconds = time % 60;
return (minutes < 10? `0${minutes}` : minutes) ':' (seconds < 10? `0${seconds}` : seconds)
}
return (
<div className="App">
<div className="wrapper">
<div className='container'>
<h1>25 5 Clock</h1>
<div className='length'>
<div className='break-length'>
<h3>Break length</h3>
<div className='adjust'>
<button onClick={decreaseBreak}>-</button>
<div className='number'>{Break}</div>
<button onClick={increaseBreak} > </button>
</div>
</div>
<div className='session-length'>
<h3>Session length</h3>
<div className="adjust">
<button onClick={decreaseSession}>-</button>
<div className='number' id='session'>{formatTime(Session)}</div>
<button onClick={increaseSession}> </button>
</div>
</div>
</div>
<Timer session={Session}/>
</div>
</div>
</div>
);
}
export default App;
CodePudding user response:
The Countdown Component never watched for changes in the session state. I Added a use effect at the top of it and changed your variables to states. Code Below.
const Countdown = (Session, isStarted) => {
console.log(Session);
// In this function Session is always 25 mins even after if i modify the state of the variable in the parent
const [InitialMinutes, setInialMinutes] = useState(Session / 60);
const [InitialSeconds, setInitialSeconds] = useState(Session % 60);
const [minutes, setMinutes] = useState(InitialMinutes);
const [seconds, setSeconds] = useState(InitialSeconds);
useEffect(() => {
setInitialSeconds(Session % 60);
setInialMinutes(Session / 60);
setMinutes(InitialMinutes);
setSeconds(InitialSeconds);
console.log(minutes);
}, [Session]);
useEffect(() => {
if (isStarted) {
let myInterval = setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(myInterval);
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000);
return () => {
clearInterval(myInterval);
};
}
}, [minutes, seconds, isStarted]);
return (
<div>
{minutes === 0 && seconds === 0 ? null : (
<h1>
{" "}
{minutes}:{seconds < 10 ? `0${seconds}` : seconds}
</h1>
)}
</div>
);
};
function Timer({ session }) {
const [isStarted, setIsStarted] = React.useState(false);
return (
<div className="timer">
<h3>Session</h3>
{Countdown(session, isStarted)}
<button onClick={() => setIsStarted(true)}>start</button>
<button>stop</button>
<button>{session}</button>
</div>
);
}
export default Timer;