Now that we've seen how "hydration" works,
let's make another improvement
to our ThemeSwitch component.
At the moment the user can enable "Dark Mode",
but if they reload the page,
it reverts to the default colours.
It would be nice to remember
this user setting.
A simple way to save
small amounts of data,
like user preferences,
is to use Local Storage.
That we can inspect here
using the Chrome Developer Tools.
Local Storage can save
simple "key/value" pairs.
At the moment there's nothing stored
for our website.
But if you do have some data
stored by some other app
you've been developing locally,
then you can just "Clear All".
So how can we save the "darkMode" setting
into Local Storage
from our app code?
When the user clicks the button
we want to not only change the value
the "darkMode" state variable,
but also save it to Local Storage.
So let's write a separate function
to handle the "click" event.
In that function we still want
to call "setDarkMode" as before.
And now we can pass this
"handleClick" function as the handler.
So far this makes no difference,
we just moved some code
from one place to another.
But now we can add another line here.
We want to use "localStorage",
that's available as a global object
in the browser,
and call its "setItem" method,
passing the "key", that is
the name of the property we want to save,
and then its value.
Just like when we call "setDarkMode"
here we want to toggle
the current "darkMode" value,
so if it was "false" we'll save "true".
Now, we need to be careful
because this expression is a boolean,
while "setItem" expects a string.
So to convert the boolean to a string
I'm going to use "JSON.stringify()".
This may look a bit strange at first,
but if you convert a boolean to JSON
you get either "true" or "false" as a string,
which is exactly what we need.
Let's save this, and test it out.
If we click "Light Mode",
you can see that in Local Storage
it saved "darkMode: false".
And if we click again,
the value of "darkMode" in the storage
becomes "true".
Good. So we're saving the setting.
But, if we reload the page,
it still shows a white background,
because we're not actually reading
that "darkMode" value from Local Storage.
Let's go and modify our code to do that.
Instead of always passing "false"
as the initial value to "useState",
we want to read the initial value
from Local Storage.
And to do that it's better
if we write a separate function.
I don't know if you know this already,
but you can pass a function to "useState",
to compute and return the initial value.
So let's write a separate function.
Let's call it "loadDarkMode".
And here we want to get
the saved "value" from "localStorage,
by calling the "getItem" method,
and passing the same "key"
we used when saving the data.
Now, we need to think about
what happens if there is no "value"
saved in Local Storage.
A value will be saved
only when the user clicks the button,
but if the user is opening our app
for the first time for example,
there will be nothing in Local Storage.
Let's look at the documentation
for the "getItem" method.
It says it "returns the current value"
"or null if the given key does not exist".
So when returning
the initial value for "darkMode"
we first need to check
if the "value" is null.
In this case we can return "false",
meaning that if the user hasn't made a choice yet
we'll default to not using dark mode.
Otherwise, if there is a value stored,
we need to parse that "value" from JSON,
because we used "JSON.stringify"
when saving it.
"JSON.parse" will do the opposite,
and convert the string back to a boolean value.
Ok. So at this point
we can pass "loadDarkMode"
as the initialiser function to "useState".
And if we save,
this seems to work.
We can see that the page
is now displaying a dark background,
which means it loaded the "darkMode" setting
from Local Storage,
where it was saved as "true"
and therefore "dark mode" is enabled.
However the page was updated using Fast Refresh,
which happens entirely on the client-side.
Let's see what happens if we reload the page,
meaning that we request it from the server.
We now get an error, saying
"localStorage is not defined".
This may seem surprising at first.
How come "localStorage" now is not defined,
when we used it before, to save the data?
The explanation is that
it's not defined on the server.
If we look through the server logs,
you can see that the error
is being logged here.
It's happening when it's trying to
pre-render our page component on the server.
And this is one of those things
that are different in Next.js
compared to a normal React app.
We always need to remember that
some of our code will run
not just in the browser,
but on the server as well.
In the next video we'll see
how to fix this issue.