reactjs 无法使用React在本地存储中正确持久保存数据

w41d8nur  于 2022-11-29  发布在  React
关注(0)|答案(1)|浏览(173)

我混合使用useContext和useEffect将useContext数据持久化在本地存储中。由于条件呈现,我无法这样做。这里的情况是,我希望在用户未登录时有一个登录按钮,在用户登录时有一个注销按钮。
在Codesanbox中,我修复了模态中的登录按钮,将“user”的初始空状态更改为“User is logged in”。
SignInDialog.js中,我有一个useEffect,我将登录模态的isOpe n prop作为依赖值传递给它。因此,每次打开和关闭它时,它都应该记录“useEffect setItem 2”。只打开模态并通过单击侧面来关闭它的测试带来了成功的结果。在我按下模态中的登录按钮后,模态关闭。但是useEffect没有被触发。
然后,在父组件中使用“user”的值来有条件地呈现“sign in”或“log-out”按钮。
当我删除它时,一切都按预期工作。问题似乎是呈现父组件和子组件的顺序。我想不出一种方法来解决这个问题,而不改变我的方法。

用户上下文.js

import { createContext } from "react";

export const UserContext = createContext(null);

应用程序js

export default function App() {
  const [user, setUser] = useState();

  return (
    <div className="App">
      <UserContext.Provider value={{ user, setUser }}>
        <Main />
      </UserContext.Provider>
    </div>
  );
}

主文件.js

export default function Main() {
  const { user, setUser } = useContext(UserContext);

  const logOut = () => {
    setUser(null);
  };

  return (
    <div className="App">
      {/* If I only have SignInButton and no conditional render it works  */}
      {/* <div>
          <SignInButton />
      </div> */}

      {user ? (
        <div>
          <Typography>{user}</Typography>
          <Button onClick={logOut}>Log out</Button>
        </div>
      ) : (
        <div>
          <SignInButton />
        </div>
      )}
    </div>
  );
}

登录按钮.js

const SignInButton = () => {
  const [openSignInDialog, setOpenSignInDialog] = useState(false);

  const handleSignInClickOpen = () => {
    setOpenSignInDialog(true);
  };

  return (
    <StyledEngineProvider injectFirst={true}>
      <div>
        <Button onClick={handleSignInClickOpen}> Sign in </Button>
        <SignInDialog open={openSignInDialog} setOpen={setOpenSignInDialog} />
      </div>
    </StyledEngineProvider>
  );
};
export default SignInButton;

登录对话框.js

export default function SignInDialog(props) {
  const { user, setUser } = useContext(UserContext);

  useEffect(() => {
    console.log(">>>>>>>useEffect getItem 1");
    /* const data = window.localStorage.getItem('uli')
    console.log(`data = ${data}`) */
  }, []);

  useEffect(() => {
    console.log(">>>>>>>useEffect setItem 2");
    /* window.localStorage.setItem('uli', user) */
  }, [props.open]);
  {
    /* end goal is to pass user as dependency but left like this for testing purposes */
  }

  const test = () => {
    setUser("User logged in");
    props.setOpen(false);
    {
      /* props.setOpen(false) doesn't make no difference */
    }
  };

  const handleClose = () => {
    props.setOpen(false);
  };

  return (
    <div className="App">
      <Dialog open={props.open} onClose={handleClose}>
        <Box component="form">
          <DialogTitle>Sign in data</DialogTitle>
          <DialogContent>
            <DialogContentText>username, password..</DialogContentText>
          </DialogContent>
          <DialogActions>
            <Button type="button" onClick={test}>
              Sign in
            </Button>
          </DialogActions>
        </Box>
      </Dialog>
    </div>
  );
}

w46czmvw

w46czmvw1#

SignInDialog.js中,你正在设置useEffect中的本地存储,并将props.open作为依赖项。因此您的useEffect从未运行。您可以按如下所示更改test并删除该useEffect

const test = () => {
  let user = "User logged in";
  setUser(user);
  localStorage.setItem("uli", JSON.stringify(user));
  props.setOpen(false);
};

然后,在App.js中,按如下所示更改user定义,因此,在此之前,您将检索本地存储(如果有)中的内容:

const [user, setUser] = useState(
  localStorage.getItem("uli") ? JSON.parse(localStorage.getItem("uli")) : null
);

相关问题