Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
In this video, we'll use the componentDidMount()
lifecycle method to make the stopwatch tick. React's built-in lifecycle methods get called at each point in a component's life-cycle. The methods act as hooks you can use to run code at key times in the life-cycle. This gives you the ability to control what happens when a component mounts, updates and unmounts.
All right, the first thing we'll do
is create a new function called tick.
0:00
This is going to be the most
essential piece of our stopwatch.
0:06
All the code that involves making
the timer tick second after second will be
0:09
written here in the tick function.
0:13
In order to produce a timer that
updates or ticks by the second,
0:15
the tick function will need to be called
continually as long as the stopwatch
0:18
component is mounted onto the DOM or
as long as it's visible on the screen.
0:21
So how we call tick over and over again?
0:26
Well, we don't wanna call it in
the render method because render is for
0:28
rendering only.
0:32
Instead, we can use one of React's
built in lifecycle method.
0:33
In React,
every component instance follows a cycle.
0:36
It's mounted onto the DOM, it's updated
with changes in data, and finally,
0:40
it's unmounted from the DOM.
0:44
This is referred to as
the component lifecycle.
0:46
React provides built in lifecycle methods
0:49
that get called at each
point in the lifecycle.
0:51
The lifecycle methods act as hooks you can
run code at key times in your component's
0:54
life cycle.
0:59
This gives you the ability to control
what happens when a component mounts,
1:00
updates and unmounts.
1:03
The lifecycle method you'll likely use
most is called componentDidMount().
1:05
So let's implement this method
inside the stopwatch class.
1:09
Below the state object,
write componentDidMount().
1:12
Usually, any custom methods or functions
you write need to be called somewhere
1:19
like with an event or
from inside another function, for example.
1:23
The componentDidMount method gets called
by React as soon as a component is
1:27
inserted or mounted into the DOM.
1:31
For instance,
I'll console.log the message,
1:34
the stopwatch mounted
inside component did mount.
1:36
Over in the browser
when the app refreshes,
1:43
you immediately see the message
logged to the console.
1:45
Lifecycle methods like
component did mount are also
1:48
referred to as lifecycle hooks
because they let you hook into, or
1:51
they provide hooks to certain
parts of a component's lifecycle.
1:55
Because componentDidMount is immediately
called after a component mounts,
1:59
it's a convenient hook for
setting up timers, fetching data,
2:03
or anything else you might need to do when
your component is mounted into the page.
2:06
So now, let's set up the timer
inside componentDidMount
2:11
using the JavaScript set interval method.
2:14
Set interval repeatedly
calls a function or
2:17
executes some code with a fixed
time delay between each call.
2:20
It returns an interval ID which
uniquely identifies the interval.
2:24
So let's first type this.intervalID
= the setInterval method.
2:28
Then pass setInterval this.tick
as the function to execute and
2:34
make the time delay 100 milliseconds or
one tenth of a second.
2:40
In the tick function, I'll log the message
ticking to the console for now.
2:46
So let's see where we're
at with our timer.
2:54
If we have a look in the console,
we see that tick is being called over and
2:56
over again.
3:01
Chrome collapses it to a single line, but
3:02
notice how the number of
calls keeps increasing.
3:04
A stopwatch usually consists of
a counter that's always counting up.
3:06
We may often pause it, but
3:11
any time that the counter is
running it should be counting up.
3:12
We're going to store that data in state
with a property called elapsedTime.
3:15
This will represent the amount of
time that's passed by which we'll
3:23
initialize to 0.
3:26
Now, in order to increase the count
each time tick is called, we'll need to
3:27
calculate the amount of time since the
last tick and add it to the elapsedTime.
3:32
Ideally, the interval should always be
100 milliseconds from tick to tick.
3:37
However, it's not always guaranteed
to be exactly 100 milliseconds.
3:41
And to learn why, check out the teacher's
notes for a detailed explanation.
3:44
So instead, we should get the exact time
at which the previous tick happened and
3:48
subtract the current time from that.
3:53
That will give us a more
accurate interval.
3:55
Then we take that value and
add it to elapsed time.
3:57
So let's implement that now.
4:01
First, in order to get the time
interval between ticks,
4:02
we need to keep track of the time at
which the previous tick happened.
4:05
We'll store that information and
4:09
state using a property named previousTime
which we'll initialize to 0.
4:11
The handleStopwatch
function starts the timer.
4:17
When the timer starts,
we'll not only isRunning to true, but
4:20
also update the previous time state
using Javascript's date.now method.
4:25
So below setState,
I'll use an if statement
4:30
to update previous time only
when starting the timer.
4:34
We'll say, if not this.state.isRunning and
4:38
I'll quickly log on my switch so
the console first to test my logic.
4:43
Let's have it say starting.
4:48
Over in the browser,
we see the console logs starting
4:52
only when I click the START button, good.
4:57
Now in the if statement,
I'll update the previous
5:01
time state with this.setState and
set it to Date.now().
5:07
Date.now() returns the exact
number of milliseconds elapsed
5:14
since January 1st of 1970, or epoch time.
5:19
And it's how dates and
time are stored in Javascript.
5:22
For example,
if I type Date.now() into the console,
5:24
it returns a number
representing milliseconds.
5:28
Each time I call it, the number increases.
5:31
This will provide a convenient way
to calculate the time intervals
5:33
between clicks.
5:36
Now, nothing visually happens
in our stopwatch yet, so
5:37
let's write the remaining
parts of our tick function.
5:41
In the function,
5:43
we need to update the elapsed time
state only if isRunning is true.
5:44
So first, let's check if isRunning is
true with if (this.state.isRunning).
5:49
If true, then we'll update the timer or
tick count.
5:58
We're going to use the current time stamp
here to do the elapsed time calculation.
6:01
So I'll store the current
time in the variable
6:05
now with const now = Date.now.
6:11
Then update state with this.setState.
6:16
And we'll update two pieces of state here,
previousTime and elapsedTime.
6:22
First, we'll make sure that
previousTime is updated to now, so
6:29
we can use it to calculate the elapsedTime
or the time since the previous tick.
6:33
Now the elapsedTime value need to
increase by an interval of time,
6:37
the amount of milliseconds that
have passed since the last tick.
6:41
We can determine the elapsedTime by
calculating the difference between now's
6:45
time stamp and the time stamp stored in
state with now- this.state.previousTime.
6:51
Then we'll increase
the elapsedTime by adding
6:57
the difference to this.state.elapsedTime.
7:02
So each time tick runs,
if isRunning is true, setState is going
7:07
to update elapsedTime using the difference
between previousTime and now.
7:12
And at the same time, it's going to
be updating previousTime to Date.now.
7:19
This is executed over and over again
as long as the timer is running.
7:25
All right, now that were done
implementing the timer logic,
7:28
let's have a look at the state of
the stopwatch and React DevTools.
7:31
Select the stopwatch
component inside the header.
7:34
And you'll see that the elapsedTime and
7:37
previousTime states are set to 0
because the stopwatch isn't running.
7:39
As soon as I click the start button,
both states begin to
7:43
update in milliseconds at about 1,000 per
second which is exactly what we want.
7:46
And notice how previousTime keeps getting
overwritten which is helping us keep track
7:50
of the totalElapsed time.
7:55
Finally, by now you know that it's usually
a good idea to update state that depends
7:57
on a previous state by using
an updated callback function.
8:01
So let's pass the setState method,
8:05
an anonymous function,
with the parameter prevState.
8:08
We'll wrap the body of
the function in parentheses and
8:12
replace this.state.elapsedTime
with prevState.elapsedTime.
8:18
And since the handle stopwatch function
also updates state based on previous
8:25
state, we'll add the callback here too.
8:30
And now we can be sure
that elapsedTime and
8:38
isRunning always hold
the correct updated states.
8:40
Now the stopwatch is still not
displaying the time in the UI.
8:44
We'll add that in the next video.
8:47
You need to sign up for Treehouse in order to download course files.
Sign up