如何根据本地存储设置状态而不用初始状态覆盖它?

Mah*_*aji 6 javascript local-storage reactjs

我尝试获取调用的更新状态localstorage,但是当我控制台将其登录到其中的函数时,会给出内部设置的默认值:darkmodeuseContextApp.tsxContext.js

应用程序.tsx:

const { darkmode } = useContext(Context);

React.useEffect(() => {
  console.log(darkmode);
}, []);
Run Code Online (Sandbox Code Playgroud)

上下文.js:

import { useState, useEffect, createContext } from "react";

const Context = createContext();

function ContextProvider({ children }) {
  const [darkmode, setDarkmode] = useState(false);

  // Local Storage: setting & getting data
  useEffect(() => {
    const darkmode = JSON.parse(localStorage.getItem("darkmode"));
    if (darkmode) {
      setDarkmode(darkmode);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem("darkmode", JSON.stringify(darkmode));
  }, [darkmode]);

  const toggleDarkmode = () => {
    setDarkmode((prev) => !prev);
  };

  return (
    <Context.Provider
      value={{
        darkmode,
        toggleDarkmode,
      }}
    >
      {children}
    </Context.Provider>
  );
}

export { ContextProvider, Context };
Run Code Online (Sandbox Code Playgroud)

本地存储:

本地存储

控制台记录:

安慰

如何localstorage通过反应上下文获取最新更新的状态?

You*_*mar 4

问题

该问题是由以下原因useEffect以及您最初设置状态的方式引起的:

useEffect(() => {
  localStorage.setItem("darkmode", JSON.stringify(darkmode));
}, [darkmode]);
Run Code Online (Sandbox Code Playgroud)

上面useEffect每次darkmode变化时都会运行,而且还在挂载上。在安装上,darkmode等于false,赋予 的值useState。因此localStorage被设置为false,覆盖之前注册的任何内容。

解决方案

解决方案是更改设置状态的方式,因此您可以选择 iflocalStroge有的内容:

const [darkmode, setDarkmode] = useState(!localStorage.getItem("darkmode") ? false : JSON.parse(localStorage.getItem("darkmode")));
Run Code Online (Sandbox Code Playgroud)

超过

或者,如果您不想访问 中的本地存储useState(这可能会导致在客户端和服务器上呈现的框架(例如 Next.js)出现问题),您可以useEffect使用一种附加状态来更改您的:

const [firstRender, setFirstRender] = useState(true);
useEffect(() => {
    // This allows the `useEffect` that fetches data from local storage to run first:
    if(firstRender){
      setFirstRender(false);
      return;
    }
    localStorage.setItem("darkmode", JSON.stringify(darkmode));
}, [darkmode, firstRender]);
Run Code Online (Sandbox Code Playgroud)

在旁边

另外,要记录darkmode更改,请考虑将其添加到以下依赖项数组中useEffect

React.useEffect(() => {
  console.log(darkmode);
}, [darkmode]);
Run Code Online (Sandbox Code Playgroud)