Intro: In the part of my reactjs app, after entering mobile number, a pin code is send to the user and then a modal
is open and user should enter pin code. In this modal there is a countdown that render a progress-bar
for waiting time.
Problem: After complete progress (For example, the user has not entered a pin or received a message), resend button is appears and if user click on, this progress should be reset.
Question: How to reset progress-bar
by clicking on the button? Or How to reset component with initial states?
Code: CounterProgress
import React, { useEffect, useState } from 'react'
import Countdown from "react-countdown";
import { Button, LinearProgress,} from "@material-ui/core";
function CounterProgress() {
const waitingTime = 10000;
const [counterRemained, setCounterRemained] = useState(waitingTime);
const [currentTime, setCurrentTime] = useState(Date.now() + counterRemained);
const [resend, setResend] = useState(true);
const counterRenderer = ({ minutes, seconds, completed, total }) => {
setCounterRemained(total)
const mainMin = waitingTime;
const onePercent = mainMin / 100;
const leftedPercent = total / onePercent;
return (
resend ? (
<>
<LinearProgress
variant="determinate"
value={leftedPercent}
dir="ltr"
style={{ height: "0.7rem", borderRadius: "10px" }}
className={` w-75 mx-auto`}
/>
<div style={{
display: "block",
marginLeft: "auto",
marginRight: "auto",
}}>
<Button
disabled={true}
style={counterRemained === 0 ? { textColor: "#6dd06d" } : {}}
>
resend code
</Button>
<span style={{ textColor: "black", fontSize: "10px" }}>{minutes}:{seconds}</span>
</div>
</>
) : (
<>
<Button
style={counterRemained === 0 ? { textColor: "#6dd06d" } : {}}
onClick={() => setResend(true)}
>
resend code
</Button>
</>
)
);
};
return (
<Countdown
date={currentTime}
renderer={counterRenderer}
onComplete={() => {
setResend(false);
}}
/>
);
}
export default CounterProgress;
This code work when user click button but progress-bar
is not reset and does not work.
My solutions but do not works:
CounterProgress
component using force update.countdown
. This method is working automatically and without onClick
.Using key option:
const [times, setTimes] = useState([Date.now() + waitingTime, Date.now() + 2 * waitingTime]);
const [currentTimeIndex, setCurrentTimeIndex] = useState(0);
return (
<Countdown
date={currentTime}
key={currentTimeIndex}
renderer={counterRenderer}
onComplete={() => {
console.log("completed", currentTimeIndex)
if (times.length - 1 <= times.indexOf(currentTime)) return;
setCurrentTimeIndex(currentTimeIndex + 1);
setCurrentTime(new Date(times[currentTimeIndex + 1]));
}}
/>
);
I used key
option for countdown
. I made resend state as a state three values (-1, 0, 1).
The part of code that changed:
const waitingTime = 120000;
const [counterRemained, setCounterRemained] = useState(waitingTime);
const [times, setTimes] = useState([Date.now() + waitingTime, Date.now() + 2 * waitingTime]);
const [currentTime, setCurrentTime] = useState(Date.now() + counterRemained);
const [currentTimeIndex, setCurrentTimeIndex] = useState(0);
const [resend, setResend] = useState(-1);
useEffect(() => {
// resend sms to user
if (resend === 0) { // by clicking on the button, resend be 0
setResend(-1) // for initializing
setCurrentTimeIndex(currentTimeIndex + 1);
setCurrentTime(new Date(times[currentTimeIndex + 1]));
}
}, [resend])
return (
<>
<Countdown
date={currentTime}
key={currentTimeIndex}
renderer={counterRenderer}
onComplete={() => {
if (times.length - 1 <= times.indexOf(currentTime)) return;
}}
/>
</>
);