我正在开发一个使用 Redux 进行状态管理的 React 应用程序。在我的布局组件中,我尝试仅在有用户时才显示页眉和页脚,但我面临一个问题,即它们都没有显示。 我知道这是因为用户仍然为空,但我可以找到解决方法,也尝试过订阅,但没有任何变化。
这是我的布局组件的简化版本:
import Routing from "../Routing/Routing";
import "./Layout.css";
import { NavLink, useLocation } from "react-router-dom";
import { authStore } from "../../redux/redux";
import { useEffect, useState } from "react";
import UserModel from "../../../models/UserModel";
function Layout(): JSX.Element {
const { pathname } = useLocation()
const hideHeaderPaths: string[] = ['/login']
const [user, setUser] = useState<UserModel>();
console.log(user)
useEffect(() => {
setUser(authStore.getState().user);
const unsubscribe = authStore.subscribe(() => {
const updatedUser = authStore.getState().user
setUser(updatedUser);
alert("Change")
});
setUser(authStore.getState().user);
return () => unsubscribe();
}, []);
return (
<div className="Layout" style={{ display: hideHeaderPaths.includes(pathname) ? "block" : "grid" }}>
{!hideHeaderPaths.includes(pathname) && user && <header><p>{`${user.firstName} ${user.lastName}`} |<NavLink to={"/logout"}>Logout</NavLink> </p></header>}
<main>
{/* <Main /> */}
<Routing />
</main>
{!hideHeaderPaths.includes(pathname) && <footer>this is the footer</footer>}
</div>
);
}
export default Layout;`
有人可以帮我理解为什么用户信息在初始渲染上没有正确显示吗?
我也尝试过在页眉和页脚中删除用户的条件渲染,但我仍然面临同样的问题。用户的名字和姓氏在初始渲染中显示为未定义。
要记住的重要一点:
useEffect
是异步的,并且总是在初始渲染之后发生。
在您的情况下,React 首次渲染您的组件并使用您在
useState
中提供的初始状态。您什么也没提供,这基本上是 undefined
的别名。这基本上就是您看到 undefined
的原因。然后一段时间后,调用 useEffect
并用正确的数据更新状态。
我建议进行以下更改:
const [user, setUser] = useState<UserModel>(authStore.getState().user);
这样,一旦组件安装完毕,您就可以到达商店,并且用户将在初始渲染时定义。
这不是 React 组件订阅 Redux 存储的方式。使用
useSelector
挂钩并选择适当的状态。 不要使用store.subscribe
和重复的本地状态。
示例:
import { useEffect, useState } from "react";
import { NavLink, useLocation } from "react-router-dom";
import { useSelector } from "react-redux"; // <-- import hook
import Routing from "../Routing/Routing";
import "./Layout.css";
import { authStore } from "../../redux/redux";
import UserModel from "../../../models/UserModel";
function Layout(): JSX.Element {
const { pathname } = useLocation()
const hideHeaderPaths: string[] = ['/login']
const user = useSelector(state => state.user); // <-- subscribe to user state
return (
<div
className="Layout"
style={{ display: hideHeaderPaths.includes(pathname) ? "block" : "grid" }}
>
{!hideHeaderPaths.includes(pathname) && user && (
<header>
<p>
{user.firstName} {user.lastName} |
<NavLink to="/logout">Logout</NavLink>
</p>
</header>
)}
<main>
{/* <Main /> */}
<Routing />
</main>
{!hideHeaderPaths.includes(pathname) && (
<footer>this is the footer</footer>
)}
</div>
);
}
export default Layout;