I am building a weather app with React & Tailwind & I am trying to save the users theme preference to local storage but it isn't persisting on reload
Here's my code. I don't know what I am doing wrong. I can set it switching in the storage panel in dev tools and it is saving it there but it isn't setting it to the correct theme on page reload.
function App() {
const [darkMode, setDarkMode] = useState(false);
//Call from local Storage
useEffect(() => {
const storedPreference = localStorage.getItem('prefersDarkMode');
if (storedPreference) {
setDarkMode(JSON.parse(storedPreference));
}
}, []);
//Set to Local Storage
useEffect(() => {
if (darkMode) {
localStorage.setItem('prefersDarkMode', 'true');
document.body.classList.add('dark');
} else {
localStorage.setItem('prefersDarkMode', 'false');
document.body.classList.remove('dark');
}
}, [darkMode]);
return (
<div className={darkMode ? 'flex flex-col min-h-screen bg-gray-800' : 'bg-neutral-50 flex flex-col min-h-screen'}>
<Header>
<button
onClick={() => {
setDarkMode(!darkMode);
}}
>
{darkMode ? <BsFillSunFill className="fill-neutral-100 text-2xl" /> : <BsFillMoonFill className="fill-gray-700 text-2xl" />}
</button>
</Header>
<ToastContainer theme={darkMode ? 'dark' : 'light'} />
<Footer />
</div>
);
}
export default App;
The problem I have seen in your codes is ..
the other useEffect initially calls the localStorage for prefersDarkMode
and the other one is for changing the darkmode state and setting the localStorage
when you reload the page, the darkmode state is always false, because of this
useEffect(() => {
if (darkMode) {
localStorage.setItem('prefersDarkMode', 'true');
document.body.classList.add('dark');
} else {
localStorage.setItem('prefersDarkMode', 'false');
document.body.classList.remove('dark');
}
}, [darkMode]);
this useEffect will set the prefersDarkMode in your localStorage to false every time you reload
to fix this, i added another state to check if the app already call the localStorage
const [flag, setFlag] = useState(false);
//Call from local Storage
useEffect(() => {
const storedPreference = localStorage.getItem("prefersDarkMode");
if (storedPreference) {
setDarkMode(JSON.parse(storedPreference));
}
setFlag(true);
}, []);
//Set to Local Storage
useEffect(() => {
if (flag) {
localStorage.setItem("prefersDarkMode", darkMode);
document.body.classList.toggle('dark',darkMode)
}
}, [darkMode, flag]);
so that, it won't set it back to default on reload
here is the working example https://codesandbox.io/s/goofy-nash-6fu3c5