我正在尝试使Redux状态脱离全局存储,并且在useSelector
HOC中使用WithAuth
时,我没有获得正确的状态。在我的全局状态下,有两个键:currentUser
和currentUser.isAuthenticated
。
在我的Redux开发工具中,isAuthenticated
键显示为值true
,但是当我使用该钩子时,得到false
。
我看过official documentation,但是如果我正确阅读,我找不到任何对我有帮助的东西。
有人可以告诉我我在做什么错吗?我是对Redux使用钩子的新手。谢谢。
withAuth.tsx
import React,
{ useEffect } from "react";
import { useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import { Routes } from "../../constants/RoutesNames";
import { DefaultRootState } from "../../store/reducers";
interface Props
{
ComponentToBeRendered: React.FC<unknown>
props?: any
};
const stateSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated;
const WithAuth : React.FC<Props> = ({ ComponentToBeRendered, props }) =>
{
const isAuthenticated = useSelector<DefaultRootState, boolean>(stateSelector);
const history = useHistory();
useEffect(() =>
{
if (!isAuthenticated) history.push(Routes.SIGN_IN);
}, [ isAuthenticated, history ]);
return (
<ComponentToBeRendered {...props} />
)
}
export default WithAuth;
答案 0 :(得分:0)
错误值表示什么?您可以为该问题添加更多信息吗?
还请记住,您可以简化这样的语句的返回,以使代码更简洁:
const stateSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated
答案 1 :(得分:0)
事实证明,useSelector
钩对Redux状态做了双重处理。如果您将console.log
(console.log("Got isAuth", isAuthenticated);
)放在useEffect
挂钩中,则会看到第一个日志为Got isAuth false
,第二个为Got isAuth true
。
我不知道这是否是完整的故事,但是到目前为止,我已经重新实现了WithAuth
来接受渲染的元素而不是要渲染的组件。然后,我有条件地返回该元素或呈现的登录页面。因此,
import React from "react";
import { useSelector } from "react-redux";
import AuthFlow from "../../pages/AuthFlow";
import { DefaultRootState } from "../../store/reducers";
interface Props
{
ComponentToBeRendered: React.ReactElement;
};
const isAuthenticatedSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated;
const WithAuth : React.FC<Props> = React.memo(({ ComponentToBeRendered }) =>
{
const isAuthenticated = useSelector<DefaultRootState, boolean>(isAuthenticatedSelector);
return (
isAuthenticated ? ComponentToBeRendered : <AuthFlow />
)
})
export default WithAuth;
我不知道这是否是最好的方法,但是我现在已经找到了解决方法。奇怪的是useSelector
不能仅在第一次运行时正确获得Redux状态。也许我想不到有人可以给我看的东西。
=========== 编辑 ==========
我对此进行了更多思考,出于各种原因,我认为这种方法可能会更好
import React from "react";
import { useSelector } from "react-redux";
import BasicTextLink from "../../components/BasicLink/BasicLink";
import { Routes } from "../../constants/RoutesNames";
import { DefaultRootState } from "../../store/reducers";
interface Props
{
ElementToBeShown: React.ReactElement;
};
const isAuthenticatedSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated;
const WithAuth : React.FC<Props> = React.memo(({ ElementToBeShown }) =>
{
const isAuthenticated = useSelector<DefaultRootState, boolean>(isAuthenticatedSelector);
return (
isAuthenticated ? ElementToBeShown : <h2>You are not signed in. Please {
<BasicTextLink baseColor useHoverEffect darkHover to={Routes.SIGN_IN} underline={"hover"}>
sign in
</BasicTextLink>
} first</h2>
)
});
export default WithAuth;