I have this piece of code in React. I want to push a fragment of my state to local storage to keep a chosen theme on page refresh. Toggle itself works fine until I want to get the value from local storage:
import React, { useEffect, useState } from 'react';
import './ThemeToggle.css'
export function ThemeToggle() {
const [ isDark, setIsDark ] = useState(true);
const root = document.querySelector(':root')
const storeUserSetPreference = (pref) => {
localStorage.setItem("isDark", pref);
};
const getUserSetPreference = () => {
return localStorage.getItem("isDark");
};
const changeThemeHandler = () => {
setIsDark(!isDark)
storeUserSetPreference(isDark)
}
useEffect(() => {
let userPref = getUserSetPreference()
console.log(userPref)
if(!isDark){
root.classList.add('dark')
} else {
root.classList.remove('dark')
}
}, [isDark, root.classList ])
return (
<div className='toggle'>
<input type='checkbox' id='darkmode-toggle' onChange={changeThemeHandler} defaultChecked={!isDark} />
<label for='darkmode-toggle' id='toggle-label' />
</div>
)
}
But as soon as I try to get value from local storage in useEffect like this:
useEffect(() => {
let userPref = getUserSetPreference()
console.log(userPref)
if(!iuserPref){
root.classList.add('dark')
} else {
root.classList.remove('dark')
}
}, [isDark, root.classList ])
then it doesn’t work anymore. I get the proper value logged to my console.
I also tried adding userPref as dependency but then I get error that userPref is not defined. Any ideas?
Here is a sandbox version where I was able to replicate this issue:
2
Answers
Local storage only save strings and you are saving "false" or "true" in your local storage not false and true itself. they are string not boolean but in your code you used it as a boolean.
if you change your useEffect to this it will solve the error:
The issue with LocalStorage is that it only works with strings. When you try to store a boolean value, it gets automatically converted to a string. Therefore, if you use localStorage.getItem(‘isDark’), it will return either the string ‘true’ or ‘false’, but both of these strings will be considered truthy values in JavaScript. So you need to explicitly serialize values
If I understand your code correctly, you can simplify it significantly:
Sandbox