React 上下文:开发者工具中的 SessionStorage 数据出现但在导航栏中显示为空白
React Context: Sessionstorage data in developer tools appears but appears blank in navbar
我正在使用 React Context 将数据存储到 sessionstorage 中以用于登录和注销。我保存了三样东西:用于保存用户 ID 的 IDContext、用于保存用户用户名的 UserNameContext 以及用于简单查看登录用户是否为管理员的 AdminContext。我想在导航栏上显示登录用户的用户名,例如 (Welcome, {user}) 但它只显示为 (Welcome, {})。我通过开发者工具检查了sessionstorage,它显示
username:""user""
那么为什么它在导航栏上显示为空白,我没有正确抓取数据吗?
auth.js:
import { createContext, useContext } from "react";
export const UserNameContext = createContext();
export const IDContext = createContext();
export const AdminContext = createContext();
export function useUserName() {
return useContext(UserNameContext);
}
export function useID() {
return useContext(IDContext);
}
export function useAdmin() {
return useContext(AdminContext);
}
navbar.js:
import React from "react";
import { Navbar, Nav, Container } from "react-bootstrap";
import { Link } from "react-router-dom";
import { useID, useUserName, useAdmin } from "../context/auth";
function Navigation(props) {
const { IDTokens } = useID();
const { usernameTokens } = useUserName();
const { adminTokens } = useAdmin();
function adminNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${usernameTokens}`}>Welcome, {usernameTokens}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
)
}
function loggedInNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${usernameTokens}`}>Welcome, {usernameTokens}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
)
}
function guestNav() {
return(
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to="/register">Register</Link>
<Link to="/login">Login</Link>
</Nav>
</Navbar.Collapse>
)
}
return (
<Navbar bg="primary" variant="dark" expand="md">
<Container>
<Link to="/">Flaskagram</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
{IDTokens && adminTokens ? (
adminNav()
) : IDTokens ? (
loggedInNav()
) : (
guestNav()
)}
</Container>
</Navbar>
)
}
export default Navigation;
好吧,如果您的本地存储中已有该项目,您可以在加载时使用 useEffect 挂钩获取它。
例如这样:
useEffect(() => {
const cachedUserName = JSON.parse(localStorage.getItem('username'));
if (cachedUserName ) {
setUserName(cachedUserName);
}
else {
...your logic
}
}, [setUserName]);
您不需要三个单独的上下文来存储这 3 条信息。要使您的用户对象可从您应用中的任何位置访问,请在 App.js 内添加此行(在 App 函数的开头):
const [user, setUser] = useState();
确保在 App.js 中导入了 useState 挂钩,以及从定义上下文的任何地方导入了 UserContext(在你的情况下,我相信它是 auth.js)。
然后,使用上下文提供程序包装从 App.js 返回的所有 jsx 元素,如下所示:
export default function App() {
const [user, setUser] = useState();
// any other code you might have here
return (
<UserContext.Provider value={{ user, setUser }}>
// all your app's components here
</UserContext.Provider>
);
}
在 auth.js 中,这就是您所需要的:
import React from "react";
const UserContext = React.createContext();
export default UserContext;
无论您在何处设置用户对象(最有可能在您的登录页面上),只需使用以下行访问 setUser 函数(并且不要忘记导入 UserContext):
const { setUser } = useContext(UserContext);
现在,在navbar.js:
import React, { useContext } from "react";
import { Navbar, Nav, Container } from "react-bootstrap";
import { Link } from "react-router-dom";
import UserContext from "../context/auth";
function Navigation() {
const {
user: { username, isAdmin },
} = useContext(UserContext);
function adminNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${username}`}>Welcome, {username}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
);
}
function loggedInNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${username}`}>Welcome, {username}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
);
}
function guestNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to="/register">Register</Link>
<Link to="/login">Login</Link>
</Nav>
</Navbar.Collapse>
);
}
return (
<Navbar bg="primary" variant="dark" expand="md">
<Container>
<Link to="/">Flaskagram</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
{username && isAdmin
? adminNav()
: username
? loggedInNav()
: guestNav()}
</Container>
</Navbar>
);
}
export default Navigation;
为了使此实现起作用,当您登录用户时,用户对象必须设置 isAdmin
和 username
的属性,以便可以在导航栏中访问它们。 isLoggedIn
属性 是不必要的,因为如果用户名 属性 不为空,则意味着用户必须登录。
我正在使用 React Context 将数据存储到 sessionstorage 中以用于登录和注销。我保存了三样东西:用于保存用户 ID 的 IDContext、用于保存用户用户名的 UserNameContext 以及用于简单查看登录用户是否为管理员的 AdminContext。我想在导航栏上显示登录用户的用户名,例如 (Welcome, {user}) 但它只显示为 (Welcome, {})。我通过开发者工具检查了sessionstorage,它显示
username:""user""
那么为什么它在导航栏上显示为空白,我没有正确抓取数据吗?
auth.js:
import { createContext, useContext } from "react";
export const UserNameContext = createContext();
export const IDContext = createContext();
export const AdminContext = createContext();
export function useUserName() {
return useContext(UserNameContext);
}
export function useID() {
return useContext(IDContext);
}
export function useAdmin() {
return useContext(AdminContext);
}
navbar.js:
import React from "react";
import { Navbar, Nav, Container } from "react-bootstrap";
import { Link } from "react-router-dom";
import { useID, useUserName, useAdmin } from "../context/auth";
function Navigation(props) {
const { IDTokens } = useID();
const { usernameTokens } = useUserName();
const { adminTokens } = useAdmin();
function adminNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${usernameTokens}`}>Welcome, {usernameTokens}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
)
}
function loggedInNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${usernameTokens}`}>Welcome, {usernameTokens}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
)
}
function guestNav() {
return(
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to="/register">Register</Link>
<Link to="/login">Login</Link>
</Nav>
</Navbar.Collapse>
)
}
return (
<Navbar bg="primary" variant="dark" expand="md">
<Container>
<Link to="/">Flaskagram</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
{IDTokens && adminTokens ? (
adminNav()
) : IDTokens ? (
loggedInNav()
) : (
guestNav()
)}
</Container>
</Navbar>
)
}
export default Navigation;
好吧,如果您的本地存储中已有该项目,您可以在加载时使用 useEffect 挂钩获取它。
例如这样:
useEffect(() => {
const cachedUserName = JSON.parse(localStorage.getItem('username'));
if (cachedUserName ) {
setUserName(cachedUserName);
}
else {
...your logic
}
}, [setUserName]);
您不需要三个单独的上下文来存储这 3 条信息。要使您的用户对象可从您应用中的任何位置访问,请在 App.js 内添加此行(在 App 函数的开头):
const [user, setUser] = useState();
确保在 App.js 中导入了 useState 挂钩,以及从定义上下文的任何地方导入了 UserContext(在你的情况下,我相信它是 auth.js)。
然后,使用上下文提供程序包装从 App.js 返回的所有 jsx 元素,如下所示:
export default function App() {
const [user, setUser] = useState();
// any other code you might have here
return (
<UserContext.Provider value={{ user, setUser }}>
// all your app's components here
</UserContext.Provider>
);
}
在 auth.js 中,这就是您所需要的:
import React from "react";
const UserContext = React.createContext();
export default UserContext;
无论您在何处设置用户对象(最有可能在您的登录页面上),只需使用以下行访问 setUser 函数(并且不要忘记导入 UserContext):
const { setUser } = useContext(UserContext);
现在,在navbar.js:
import React, { useContext } from "react";
import { Navbar, Nav, Container } from "react-bootstrap";
import { Link } from "react-router-dom";
import UserContext from "../context/auth";
function Navigation() {
const {
user: { username, isAdmin },
} = useContext(UserContext);
function adminNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${username}`}>Welcome, {username}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
);
}
function loggedInNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${username}`}>Welcome, {username}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
);
}
function guestNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to="/register">Register</Link>
<Link to="/login">Login</Link>
</Nav>
</Navbar.Collapse>
);
}
return (
<Navbar bg="primary" variant="dark" expand="md">
<Container>
<Link to="/">Flaskagram</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
{username && isAdmin
? adminNav()
: username
? loggedInNav()
: guestNav()}
</Container>
</Navbar>
);
}
export default Navigation;
为了使此实现起作用,当您登录用户时,用户对象必须设置 isAdmin
和 username
的属性,以便可以在导航栏中访问它们。 isLoggedIn
属性 是不必要的,因为如果用户名 属性 不为空,则意味着用户必须登录。