Alright so in this video we're going to work on the timer so 1
you'll see that when we start the application we want 2
something like this we want a progress bar a circular 3
progress bar we're going to go from for example 10 to 0 and 4
when it's going to reach zero the question is going to be 5
marked as invalid here and we're going to move to the next 6
question okay and during the animation the timer is going to 7
be removed from the screen so to do that we are going to use 8
the circular progress from chakra so it's pretty simple if 9
you go into the doc you can see that we can use these two 10
components circular progress and circular progress label 11
here and basically we can define a max here and a value 12
so for example if I set max 10 and 1 as value the circular 13
progress is going to fill up okay here 2345 et -cetera and 14
you can use the same value here okay to display the correct 15
label so that's what we're going to to create the timer. 16
Um so you can try to do it by yourself but be careful there 17
is a trap. There is a trap related to set interval, okay? 18
When you call a set state in set interval, you have to be 19
careful and not do a regular set state. Okay? So I don't 20
know if you know that but if you look on different 21
documentation of react when you you are doing a set something 22
when you use a state you can basically pass a value or you 23
can pass a callback, a function and this function actually is 24
going to use the previous value of the state and this is safer 25
than doing what we do usually okay because this is not going 26
to work as expected when you call it in a set interval or in 27
a set time out or thing like this okay so in general if you 28
want to be super safe you should always use this approach 29
if you don't know when to use one on or when to use the other 30
one okay but I usually use this because I know when only to use 31
this one okay this is to avoid state closure I will talk about 32
that later but in this case when you're going to create a 33
timer use this approach okay all right so good luck and now 34
we're going to see how to do it okay so what we can do is we 35
can create the timer component so timer. TSX I'm not putting 36
it in the components folder again because we're going to 37
use it only once but since only related to play quiz, what I'm 38
going to do is I'm going to create a folder that I'm going 39
to call play quiz. I'm going to put play quiz in it and the 40
timer in it. Like this I'm going to make a component here. 41
Timer, okay? And in play quiz, we're going to use it. Oh by 42
the way, make sure to update your import in app, okay? I 43
think it's been done automatically for me, yes. But 44
be careful, update it. Uh so so so in play quiz below the 45
progress bar for example we could create a box that is 46
going to be positioned absolutely and I'm going to put 47
it at top 50 and right 50 and here we're going to call the 48
timer So we're just going to display this box in this timer 49
when the question is unanswered. So it's been always 50
displayed as long as you haven't touched anything. As 51
soon as there is an animation running is going to be removed. 52
And when the animation is going to be finished and the question 53
will be unanswered again then it's going to reappear. Okay 54
and reset. So we are going to display all that only if the 55
question status is unanswered. Oh and I killed it a little 56
bit. Okay, like this. Oh, I forgot to curly brace. Okay. 57
All right all right so let's see if I go there okay timer 58
great and technically it should be removed yes when I do that 59
and it should reappear yes okay we're we're good so now we can 60
work in the timer so like I told you the timer is going to 61
come from a circular progress like this so we're going to use 62
it and we're going to need the circular progress and the 63
circular progress label we're going to import that Okay and 64
and and we have an example yes we have exactly what we want 65
over here so we're going to paste this example okay so I'm 66
not going to change the color I'm going to use the default 67
one here it will be something like this let's see already if 68
it's working okay okay now we just have to use the correct 69
values and make it update So it means that we first have to 70
define a max value here. Uh so maybe we could send that as a 71
props. So I'm going to do P and we'll have a max that will be a 72
number. And this is going to be P dot max. Then the value well 73
is going to be calculated inside the component. So we're 74
going to have a store to store this value. I'm going to call 75
that progress. Like this it's going to be a useState and don't 76
forget to type it it's going to be a number by default it's going 77
to start from the maximum so Uh p.max so we're going to send that 78
here max and we could say that it's going to be ten for now. 79
Okay, so what we're going to do now is we want to decrease the 80
value by one every second. So we're going to use a use 81
effect a useEffect that is going to run on startup after 82
the first render and here we're going to use a set interval. So 83
set interval run a function like this and it's going to run 84
every one second. So what do we want to do every second well we 85
want to set the progress to progress minus one and that is 86
exactly what is going to cause an issue if you do that okay we 87
can start trying to do that and you see that it's going to 88
cause an issue so already if we set the progress here and here 89
so progress you're going to notice that it is not going to 90
work it's going to start at 10 and go to nine and never move 91
again and this is because like I told you this is a closure 92
and so what is going on here is that set interval here is going 93
to keep in memory what is the initial value for progress and 94
it's 10 and it's going to run every second with the same 95
function with the same value so you're going to have 10 minus 96
one that is going to run every second so you'll still have 97
nine , nine , nine, every seconds that is why you have to use the 98
callback here we have the previous progress and use this 99
one this way you are sure that you will always have the the 100
freshest value if I may say in your set state here and now it 101
seems that 102
it's working. It's working but we're going to have an issue 103
when we're going to reach zero because this is going to 104
continue decreasing. Okay? That's not exactly what we 105
want. So we have to track when we are at zero and if we are at 106
zero, we need to trigger something. Okay? At least tell 107
our parent that we are finished. So we're going to 108
prepare a callback here. That is going to be on finished. I 109
is going to be just a signal so just a function and basically 110
we have to track the progress so we're going to use a use 111
effect again 112
and listen to the progress. And we're just going to check if 113
the progress is lower or or equal to zero then well we're 114
finished so let's call onFinished. Okay? But also we 115
want to clean the interval here. Otherwise it's going to 116
keep running behind the scene and we don't want that. So it 117
means that we have to store here the timer and there is 118
actually a type that exist for a set interval okay if you pass 119
your mouse over you have the nodeJS dot timer so that is 120
what this is. So when the component amount we want to 121
clear the timer so we're going to return a function that's how 122
we're going to clean things and here we're going to clear the 123
interval timer but even if the component doesn't amount maybe 124
we want to also clear the interval when we reach zero so 125
we could also clear the interval here but hey the timer 126
is declared here so we don't have access to the timer so 127
what we can do is not declare it here we're going to declare 128
it outside of our component and that's fine that's fine because 129
this is not something that we're going to use inside the 130
return here it's not something that is rendered it's not 131
something that is related a state, okay? Uh this is just an 132
ID behind the scene. So we're just going to clear it here and 133
it should work fine. Okay so technically now at least it 134
should stop when I reach zero let's see 135
okay it stopped but something went wrong and the onFinished 136
oh is not a function obviously we're not sending onFinished 137
yet so it's crashing so we're going to send an onFinished 138
function here and actually what do we want to do when we're 139
finished well we want to set the question as failed and we 140
also want to move to the next question so what we're do is 141
we're going to create all the function is going to be fail 142
question 143
So first we're going to add an error in G story. So set 144
history and we're going to set everything that was there plus 145
an error and we're going to set the question status to invalid. 146
By doing that it's going to trigger the animation like this 147
is listening to the question status and when it's going to 148
finish everything should run correctly because it's going to 149
move to the next question and set the question status to 150
unanswered. So everything should go as expected. So here 151
onFinished we could just call fake question but instead of 152
declaring a function that call a function we can just send 153
directly the function to run. Fake question. And now let's 154
see. I'm going to refresh. Now let's wait and let's see if we 155
have an error by default when we reach zero. 156
And yeah it seems that it's working and we're moving to the 157
next question so everything is super fine okay so now we're 158
good for the timer so maybe we could move to the score screen 159
so let's do that in the next one