1
00:00:03,000 --> 00:00:05,643
Now that we've seen how "hydration" works,

2
00:00:05,643 --> 00:00:07,532
let's make another improvement

3
00:00:07,532 --> 00:00:09,358
to our ThemeSwitch component.

4
00:00:09,984 --> 00:00:12,442
At the moment the user can enable "Dark Mode",

5
00:00:12,942 --> 00:00:14,814
but if they reload the page,

6
00:00:14,814 --> 00:00:17,087
it reverts to the default colours.

7
00:00:17,653 --> 00:00:19,486
It would be nice to remember

8
00:00:19,486 --> 00:00:20,664
this user setting.

9
00:00:21,230 --> 00:00:22,660
A simple way to save

10
00:00:22,660 --> 00:00:24,233
small amounts of data,

11
00:00:24,233 --> 00:00:25,807
like user preferences,

12
00:00:25,807 --> 00:00:27,523
is to use Local Storage.

13
00:00:27,523 --> 00:00:29,240
That we can inspect here

14
00:00:29,240 --> 00:00:31,600
using the Chrome Developer Tools.

15
00:00:32,457 --> 00:00:33,893
Local Storage can save

16
00:00:33,893 --> 00:00:35,524
simple "key/value" pairs.

17
00:00:35,524 --> 00:00:37,873
At the moment there's nothing stored

18
00:00:37,873 --> 00:00:38,917
for our website.

19
00:00:38,917 --> 00:00:40,744
But if you do have some data

20
00:00:40,744 --> 00:00:42,309
stored by some other app

21
00:00:42,309 --> 00:00:44,332
you've been developing locally,

22
00:00:45,223 --> 00:00:46,945
then you can just "Clear All".

23
00:00:47,445 --> 00:00:50,446
So how can we save the "darkMode" setting

24
00:00:50,446 --> 00:00:51,764
into Local Storage

25
00:00:51,764 --> 00:00:53,081
from our app code?

26
00:00:53,811 --> 00:00:56,015
When the user clicks the button

27
00:00:56,015 --> 00:00:58,575
we want to not only change the value

28
00:00:58,575 --> 00:01:00,707
the "darkMode" state variable,

29
00:01:00,707 --> 00:01:03,124
but also save it to Local Storage.

30
00:01:03,837 --> 00:01:05,876
So let's write a separate function

31
00:01:05,876 --> 00:01:07,556
to handle the "click" event.

32
00:01:08,803 --> 00:01:10,666
In that function we still want

33
00:01:10,666 --> 00:01:12,652
to call "setDarkMode" as before.

34
00:01:13,336 --> 00:01:14,769
And now we can pass this

35
00:01:14,769 --> 00:01:17,038
"handleClick" function as the handler.

36
00:01:17,597 --> 00:01:19,485
So far this makes no difference,

37
00:01:19,485 --> 00:01:20,842
we just moved some code

38
00:01:20,842 --> 00:01:22,376
from one place to another.

39
00:01:22,994 --> 00:01:24,900
But now we can add another line here.

40
00:01:25,400 --> 00:01:27,210
We want to use "localStorage",

41
00:01:27,210 --> 00:01:29,322
that's available as a global object

42
00:01:29,322 --> 00:01:30,227
in the browser,

43
00:01:30,847 --> 00:01:32,971
and call its "setItem" method,

44
00:01:33,581 --> 00:01:35,102
passing the "key", that is

45
00:01:35,102 --> 00:01:37,500
the name of the property we want to save,

46
00:01:38,058 --> 00:01:39,367
and then its value.

47
00:01:39,367 --> 00:01:41,846
Just like when we call "setDarkMode"

48
00:01:41,846 --> 00:01:43,361
here we want to toggle

49
00:01:43,361 --> 00:01:45,358
the current "darkMode" value,

50
00:01:45,358 --> 00:01:48,043
so if it was "false" we'll save "true".

51
00:01:48,819 --> 00:01:50,346
Now, we need to be careful

52
00:01:50,346 --> 00:01:52,521
because this expression is a boolean,

53
00:01:53,079 --> 00:01:55,453
while "setItem" expects a string.

54
00:01:55,953 --> 00:01:58,524
So to convert the boolean to a string

55
00:01:58,524 --> 00:02:01,026
I'm going to use "JSON.stringify()".

56
00:02:01,026 --> 00:02:03,597
This may look a bit strange at first,

57
00:02:03,597 --> 00:02:06,099
but if you convert a boolean to JSON

58
00:02:06,099 --> 00:02:09,227
you get either "true" or "false" as a string,

59
00:02:09,227 --> 00:02:11,312
which is exactly what we need.

60
00:02:12,159 --> 00:02:14,031
Let's save this, and test it out.

61
00:02:14,531 --> 00:02:15,635
If we click "Light Mode",

62
00:02:16,135 --> 00:02:18,360
you can see that in Local Storage

63
00:02:18,360 --> 00:02:20,180
it saved "darkMode: false".

64
00:02:20,747 --> 00:02:21,551
And if we click again,

65
00:02:23,213 --> 00:02:25,601
the value of "darkMode" in the storage

66
00:02:25,601 --> 00:02:26,544
becomes "true".

67
00:02:27,106 --> 00:02:29,448
Good. So we're saving the setting.

68
00:02:29,948 --> 00:02:31,665
But, if we reload the page,

69
00:02:31,665 --> 00:02:33,829
it still shows a white background,

70
00:02:34,393 --> 00:02:36,471
because we're not actually reading

71
00:02:36,471 --> 00:02:38,977
that "darkMode" value from Local Storage.

72
00:02:39,538 --> 00:02:42,126
Let's go and modify our code to do that.

73
00:02:42,126 --> 00:02:44,325
Instead of always passing "false"

74
00:02:44,325 --> 00:02:46,590
as the initial value to "useState",

75
00:02:46,590 --> 00:02:48,724
we want to read the initial value

76
00:02:48,724 --> 00:02:49,953
from Local Storage.

77
00:02:49,953 --> 00:02:51,635
And to do that it's better

78
00:02:51,635 --> 00:02:53,705
if we write a separate function.

79
00:02:54,593 --> 00:02:56,687
I don't know if you know this already,

80
00:02:56,687 --> 00:02:59,001
but you can pass a function to "useState",

81
00:02:59,556 --> 00:03:02,331
to compute and return the initial value.

82
00:03:02,831 --> 00:03:04,956
So let's write a separate function.

83
00:03:04,956 --> 00:03:06,716
Let's call it "loadDarkMode".

84
00:03:09,132 --> 00:03:10,543
And here we want to get

85
00:03:10,543 --> 00:03:12,814
the saved "value" from "localStorage,

86
00:03:13,664 --> 00:03:15,871
by calling the "getItem" method,

87
00:03:16,371 --> 00:03:18,140
and passing the same "key"

88
00:03:18,140 --> 00:03:20,113
we used when saving the data.

89
00:03:20,681 --> 00:03:22,420
Now, we need to think about

90
00:03:22,420 --> 00:03:24,675
what happens if there is no "value"

91
00:03:24,675 --> 00:03:26,156
saved in Local Storage.

92
00:03:26,156 --> 00:03:27,508
A value will be saved

93
00:03:27,508 --> 00:03:29,891
only when the user clicks the button,

94
00:03:29,891 --> 00:03:32,081
but if the user is opening our app

95
00:03:32,081 --> 00:03:34,078
for the first time for example,

96
00:03:34,078 --> 00:03:36,590
there will be nothing in Local Storage.

97
00:03:37,540 --> 00:03:39,178
Let's look at the documentation

98
00:03:39,178 --> 00:03:40,499
for the "getItem" method.

99
00:03:41,051 --> 00:03:43,591
It says it "returns the current value"

100
00:03:43,591 --> 00:03:46,399
"or null if the given key does not exist".

101
00:03:46,965 --> 00:03:47,949
So when returning

102
00:03:47,949 --> 00:03:49,801
the initial value for "darkMode"

103
00:03:50,358 --> 00:03:51,862
we first need to check

104
00:03:51,862 --> 00:03:53,433
if the "value" is null.

105
00:03:54,001 --> 00:03:56,436
In this case we can return "false",

106
00:03:56,436 --> 00:03:59,845
meaning that if the user hasn't made a choice yet

107
00:03:59,845 --> 00:04:02,418
we'll default to not using dark mode.

108
00:04:03,057 --> 00:04:05,688
Otherwise, if there is a value stored,

109
00:04:05,688 --> 00:04:08,457
we need to parse that "value" from JSON,

110
00:04:08,457 --> 00:04:10,671
because we used "JSON.stringify"

111
00:04:10,671 --> 00:04:11,710
when saving it.

112
00:04:11,710 --> 00:04:14,063
"JSON.parse" will do the opposite,

113
00:04:14,063 --> 00:04:17,315
and convert the string back to a boolean value.

114
00:04:18,163 --> 00:04:19,648
Ok. So at this point

115
00:04:19,648 --> 00:04:21,579
we can pass "loadDarkMode"

116
00:04:21,579 --> 00:04:24,698
as the initialiser function to "useState".

117
00:04:25,347 --> 00:04:26,364
And if we save,

118
00:04:26,364 --> 00:04:27,654
this seems to work.

119
00:04:27,654 --> 00:04:29,282
We can see that the page

120
00:04:29,282 --> 00:04:31,725
is now displaying a dark background,

121
00:04:31,725 --> 00:04:34,711
which means it loaded the "darkMode" setting

122
00:04:34,711 --> 00:04:36,001
from Local Storage,

123
00:04:36,001 --> 00:04:37,901
where it was saved as "true"

124
00:04:37,901 --> 00:04:40,411
and therefore "dark mode" is enabled.

125
00:04:41,387 --> 00:04:44,754
However the page was updated using Fast Refresh,

126
00:04:44,754 --> 00:04:47,700
which happens entirely on the client-side.

127
00:04:48,271 --> 00:04:51,474
Let's see what happens if we reload the page,

128
00:04:51,474 --> 00:04:54,535
meaning that we request it from the server.

129
00:04:54,535 --> 00:04:56,456
We now get an error, saying

130
00:04:56,456 --> 00:04:58,592
"localStorage is not defined".

131
00:04:58,592 --> 00:05:01,012
This may seem surprising at first.

132
00:05:01,012 --> 00:05:04,073
How come "localStorage" now is not defined,

133
00:05:04,073 --> 00:05:06,991
when we used it before, to save the data?

134
00:05:07,919 --> 00:05:09,512
The explanation is that

135
00:05:09,512 --> 00:05:11,659
it's not defined on the server.

136
00:05:12,229 --> 00:05:13,784
If we look through the server logs,

137
00:05:14,284 --> 00:05:15,920
you can see that the error

138
00:05:15,920 --> 00:05:17,241
is being logged here.

139
00:05:17,241 --> 00:05:19,381
It's happening when it's trying to

140
00:05:19,381 --> 00:05:22,150
pre-render our page component on the server.

141
00:05:22,839 --> 00:05:25,145
And this is one of those things

142
00:05:25,145 --> 00:05:27,302
that are different in Next.js

143
00:05:27,302 --> 00:05:29,608
compared to a normal React app.

144
00:05:30,257 --> 00:05:32,464
We always need to remember that

145
00:05:32,464 --> 00:05:34,245
some of our code will run

146
00:05:34,245 --> 00:05:35,955
not just in the browser,

147
00:05:35,955 --> 00:05:37,806
but on the server as well.

148
00:05:37,806 --> 00:05:39,729
In the next video we'll see

149
00:05:39,729 --> 00:05:41,296
how to fix this issue.

