不确定我是否正确使用了 setState,因为我的状态在初始加载期间没有更新
Unsure if I'm using setState correctly because my state is not updated during initial load
我有一个状态可以存储当前应用程序的深色或浅色主题。我使用 useEffect 挂钩将状态更改存储在 localStorage 中,这样当用户刷新页面时,他们的首选主题将被保存,另一个 useEffect 挂钩在初始加载期间更新我的状态。但是,我的状态在初始加载期间不会更新。
我尝试过的事情:
- 确保在初始加载期间将 useEffect 放置在之前 useEffect 以存储主题状态
- 使用 Promise 确保我的 changeTheme 函数仅在加载状态发生变化后触发
- 我记录了我的结果,所以我知道 localStorage 在保存我的状态或跟踪更改方面没有任何问题,但是我的第一个 useEffect 挂钩中的 setState 函数没有正确更新我的状态。
下面是我的代码:
const [theme, setTheme] = useState({});
useEffect(() => {
const loadedTheme = JSON.parse(localStorage.getItem(themeStorage))
if (loadedTheme) {
console.log("Initial load")
console.log(loadedTheme);
console.log("Setting theme to localStorage")
Promise.resolve()
.then(() => { setTheme({ dark: loadedTheme.dark }) })
.then(() => { console.log(theme) })
.then(() => changeTheme())
}
}, [])
useEffect(() => {
localStorage.setItem(themeStorage, JSON.stringify(theme))
console.log("Inside useEffect to save changed theme")
console.log(theme)
}, [theme])
function changeTheme() {
console.log("Inside changeTheme function");
console.log(theme);
if (!theme || !theme.dark) { //light turns to dark
for (let vars of Object.keys(varTheme)) {
document.documentElement.style.setProperty(`--${vars}`, varTheme[vars][0]);
}
setTheme({ ...theme, dark: true })
}
else {
for (let vars of Object.keys(varTheme)) { //dark turns to light
document.documentElement.style.setProperty(`--${vars}`, varTheme[vars][1]);
}
setTheme({ ...theme, dark: false })
}
}
有点不清楚你认为问题是什么,但我怀疑你是seeing/describingtheme
第一个[=14]没有更新=] 勾.
问题
原因是 React 状态被认为是常量和不可变的。在 useEffect
回调中, theme
状态值在回调范围内关闭,无论是等待还是 Promise 链接都会更改在范围内关闭的状态值。
const [theme, setTheme] = useState({}); // <-- initial state
useEffect(() => {
const loadedTheme = JSON.parse(localStorage.getItem(themeStorage))
if (loadedTheme) {
console.log("Initial load")
console.log(loadedTheme);
console.log("Setting theme to localStorage")
Promise.resolve()
.then(() => { setTheme({ dark: loadedTheme.dark }) })
.then(() => { console.log(theme) }) // <-- still initial state
.then(() => changeTheme())
}
}, []); // <-- mounting "instance" of state
然后您从附件调用 changeTheme
,它也将访问附件的“陈旧”状态。
解决方案
LocalStorage 是同步的,因此您可以使用初始化函数从中设置初始状态。
const loadThemeFromStorage = () => {
const { dark } = JSON.parse(localStorage.getItem(themeStorage)) ?? {};
return { dark };
};
const [theme, setTheme] = useState(loadThemeFromStorage());
现在状态已经初始设置,您可以安全地在安装 useEffect
挂钩中调用 changeTheme
。
useEffect(() => {
console.log("Initial load");
console.log(theme);
changeTheme();
}, []);
useEffect(() => {
localStorage.setItem(themeStorage, JSON.stringify(theme));
console.log("Inside useEffect to save changed theme");
console.log(theme);
}, [theme]);
我有一个状态可以存储当前应用程序的深色或浅色主题。我使用 useEffect 挂钩将状态更改存储在 localStorage 中,这样当用户刷新页面时,他们的首选主题将被保存,另一个 useEffect 挂钩在初始加载期间更新我的状态。但是,我的状态在初始加载期间不会更新。
我尝试过的事情:
- 确保在初始加载期间将 useEffect 放置在之前 useEffect 以存储主题状态
- 使用 Promise 确保我的 changeTheme 函数仅在加载状态发生变化后触发
- 我记录了我的结果,所以我知道 localStorage 在保存我的状态或跟踪更改方面没有任何问题,但是我的第一个 useEffect 挂钩中的 setState 函数没有正确更新我的状态。
下面是我的代码:
const [theme, setTheme] = useState({});
useEffect(() => {
const loadedTheme = JSON.parse(localStorage.getItem(themeStorage))
if (loadedTheme) {
console.log("Initial load")
console.log(loadedTheme);
console.log("Setting theme to localStorage")
Promise.resolve()
.then(() => { setTheme({ dark: loadedTheme.dark }) })
.then(() => { console.log(theme) })
.then(() => changeTheme())
}
}, [])
useEffect(() => {
localStorage.setItem(themeStorage, JSON.stringify(theme))
console.log("Inside useEffect to save changed theme")
console.log(theme)
}, [theme])
function changeTheme() {
console.log("Inside changeTheme function");
console.log(theme);
if (!theme || !theme.dark) { //light turns to dark
for (let vars of Object.keys(varTheme)) {
document.documentElement.style.setProperty(`--${vars}`, varTheme[vars][0]);
}
setTheme({ ...theme, dark: true })
}
else {
for (let vars of Object.keys(varTheme)) { //dark turns to light
document.documentElement.style.setProperty(`--${vars}`, varTheme[vars][1]);
}
setTheme({ ...theme, dark: false })
}
}
有点不清楚你认为问题是什么,但我怀疑你是seeing/describingtheme
第一个[=14]没有更新=] 勾.
问题
原因是 React 状态被认为是常量和不可变的。在 useEffect
回调中, theme
状态值在回调范围内关闭,无论是等待还是 Promise 链接都会更改在范围内关闭的状态值。
const [theme, setTheme] = useState({}); // <-- initial state
useEffect(() => {
const loadedTheme = JSON.parse(localStorage.getItem(themeStorage))
if (loadedTheme) {
console.log("Initial load")
console.log(loadedTheme);
console.log("Setting theme to localStorage")
Promise.resolve()
.then(() => { setTheme({ dark: loadedTheme.dark }) })
.then(() => { console.log(theme) }) // <-- still initial state
.then(() => changeTheme())
}
}, []); // <-- mounting "instance" of state
然后您从附件调用 changeTheme
,它也将访问附件的“陈旧”状态。
解决方案
LocalStorage 是同步的,因此您可以使用初始化函数从中设置初始状态。
const loadThemeFromStorage = () => {
const { dark } = JSON.parse(localStorage.getItem(themeStorage)) ?? {};
return { dark };
};
const [theme, setTheme] = useState(loadThemeFromStorage());
现在状态已经初始设置,您可以安全地在安装 useEffect
挂钩中调用 changeTheme
。
useEffect(() => {
console.log("Initial load");
console.log(theme);
changeTheme();
}, []);
useEffect(() => {
localStorage.setItem(themeStorage, JSON.stringify(theme));
console.log("Inside useEffect to save changed theme");
console.log(theme);
}, [theme]);