Dark Mode Persistence with Next.js is Harder than with plain React (MUI example)
Aug 15, 2023
Dark Mode Persistence with Next.js is Harder than with plain React (MUI example)
Consider subscribing to see mo tutorials on how I built BuzzRank.io with Next.js and Firebase! Step-by-step tutorial: https://medium.com/@luca_79189/how-to … Finished project on GitHub: https://github.com/DiMatteoL/buzzrank … Link to BuzzRank: https://www.buzzrank.io 📚 Chapters 00:00 - Persistent Dark Modes in Next.js are not as simple as they seem 00:08 - How Persistent Dark Modes work for React apps 00:15 - Why Persistent Dark Modes are flickering in Next.js apps 00:34 - How to fix the Dark Mode Flicker in Next.js apps 00:57 - Tutorial: Persistent Dark Modes with Next.js and MUI 01:18 - Get a runnable Next.js app (here with MUI) 01:49 - Use next-themes ThemeProvider to set your page’s data-theme 02:27 - Update the theme from our app with the useTheme React hook 02:48 - Dynamically change MUI’s theme 03:12 - Final result: A deployed app with persistant light and dark modes 🎶 Music On My Way by Ghostrifter Official | https://soundcloud.com/ghostrifter-of … Music promoted by https://www.chosic.com/free-music/all/ Creative Commons CC BY-SA 3.0https://creativecommons.org/licenses/ … #Nextjs #MUI #DarkMode
Content
0.08 -> Implementing a persistent
dark mode in your Next.js app,
3.12 -> easy enough right?
Well it's not that simple and here is why.
7.04 -> The way to make a dark mode persistent
is usually to store a "theme" value in
10.72 -> your clients local storage and count
on them to render their own theme.
14.4 -> But with Next you render React pages on the
server, so if you take the same approach you might
19.28 -> end up facing the dreaded "Dark Mode Flicker".
Here's johnny.
24.4 -> Yeah that's right, major websites like the home
page for Material UI or Chakra UI suffer from
29.68 -> this problem and although it's not the worst
problem, it still accounts for a bad user
33.84 -> experience, so let's see how to fix it.
Well the server side rendered page is
38.16 -> displayed on the client before the theme can be
updated so we don't have too many options here:
42.96 -> We need to add a script to our pre-built HTML
pages to prevent them from being displayed
47.68 -> until the local storage theme value has been
read and the css variables have been updated
52.16 -> and only then can the page be displayed.
There's a library called next-themes
56 -> that can do this for us.
Now that we know how it works
58.4 -> let's see how to do it in practice and how I've
implemented it with Material UI in my own project
63.52 -> BuzzRank. If you don't use Material UI
don't worry the logic will be the same.
67.52 -> For those who want to follow along see the
step-by-step link in the description and for
72.16 -> those who want to see the finished project I've
also added a link to the public GitHub repository.
76.8 -> Alright let's get going.
From the Material UI GitHub repository,
80.24 -> copy the instructions on the "Next.js with
TypeScript" example and paste it in your terminal.
85.04 -> And then run "npm install".
At that point we have a
87.76 -> Next.js with Material UI project.
Now let's clean it up a little.
91.6 -> With most JavaScript UI libraries you'll
have a ThemeProvider in your "_app.tsx" file.
96.8 -> You want to move it to another component
that we'll call "PageProvider" under
100.4 -> the "src" folder so that at the end your
_app.tsx and PageProvider look like this.
105.76 -> Feel free to pause the
video if you need more time.
108.16 -> Now that we've done this
let's implement our dark mode.
110.96 -> Let's start by installing the library called
"next-themes" then add the ThemeProvider from
116 -> next-themes to the root of your app
component. This provider prevents the
119.52 -> display of the page as long as the HTML
"data-theme" value hasn't been updated.
123.76 -> Here it is set to light by default. And
now we just want to set our css "color" and
128.32 -> "background-color" depending on the "data-theme".
With MUI you can do this with the "GlobalStyles"
133.44 -> component to which we can
give a light background for
136.08 -> light mode and a dark background for dark mode.
To make sure this works properly we can go back
140.32 -> to our project and switch the "data-theme" from
light to dark here you can see that the background
144.8 -> and the text are properly changing colors.
To do that from the app we have access to
148.64 -> the "useTheme" React hook that i will call from
the pages/index.tsx file. It gives us access to
154.96 -> the current theme and to a method to change it.
And by pairing them with the button we now have
159.76 -> an app that can change themes, persist
them, and never flickers on reloads.
164.4 -> As you can see here, if i change
the page the theme is persisted.
168.48 -> So, that would be the end if we didn't use
Material UI but since we use it, we also need
173.12 -> to inform it that the theme has been changed.
If we go into our "theme" file into our "src"
177.84 -> directory we can see that we only have one
theme at the moment and we want to create two,
182.24 -> one for light and one for dark.
And we also want to go back
184.8 -> to our page provider and update the
theme accordingly using React hooks.
188.96 -> Alright I took the time to make the app
a little prettier and I deployed it to
192.8 -> Vercel and here is the final result.
If you want to check it for yourself,
196.72 -> the link is in the description.
And that's how you get a persistent
199.84 -> dark mode using Next.js and Material UI.
This video is part of a tutorial series on
204.8 -> how i built buzzRank.io with Next.js and Firebase
so if you're interested in those tools or want
210.4 -> to know the story of how i built buzzRank, you
know what to do, subscribe, it would also mean
215.2 -> the world to me.
See ya
Source: https://www.youtube.com/watch?v=kIkdoW6VUIQ