小能豆

如何重定向到React中的登录页面

javascript

我在 React 中设置私有路由中间件时遇到问题。访问私有路由时,我调用“RequireAuth”组件来验证身份验证令牌是否有效。出现这种困境是因为验证是异步的并且会改变上下文的状态。结果,我有两个渲染:第一个返回“null”,第二个返回实际值。

我考虑了替代方案,例如使用另一个状态来指示异步方法正在加载,从而避免在第一次渲染期间在中间件中进行验证,其中值仍然为空。它有效,但我认为这并不理想!当“用户”状态发生变化时更新上下文非常重要,但我不确定这种类型的验证是否真的需要两个渲染,我只需要知道令牌是否有效。

使用实际值而不是“null”初始化“用户”状态是一种选择,但如果没有 useEffect,这将导致每次上下文状态更新时产生多个 API 请求。

第一个上下文返回,第二个上下文在异步方法之后:

在此输入图像描述

目前情况如何:

const RoutesApp = () => {
return (
  <BrowserRouter>
    <Routes>
      <Route path="/home" element={<RequireAuth><Home /></RequireAuth>} />
      <Route path="/login" element={<Login />} />
      <Route path="*" element={<Navigate to="/home" />} />
    </Routes>
  </BrowserRouter>
);
};

export default RoutesApp;

--------------------------------------------------
export const RequireAuth = ({ children }: { children: JSX.Element }) => {
const auth = useAuth(); // Hook by Auth Context

if (!auth.user) {
  return <Navigate to="/login" />
}
return children;

};

--------------------------------------------------
export const AuthProvider = ({ children }) => {

const [user, setUser] = useState(null);
const api = useApi();

useEffect(() => {
  validToken()
}, []);

...

const validToken = async () => {
  const storageData = localStorage.getItem("authToken");
  if (storageData) {
    const data = await api.validateToken(storageData);
    if (data.user) {
      setUser(data.user);
    }
  }
}

return (
  <AuthContext.Provider value={ user, ...}> 
    {children}
  </AuthContext.Provider>
);
}
```

阅读 108

收藏
2024-02-27

共1个答案

小能豆

看起来你在React中遇到了一个常见的问题,特别是在处理身份验证和管理用户会话时。让我们讨论一种解决这个问题的潜在方法。

你可以采取的一种方法是使用加载状态来指示身份验证验证过程正在进行中。这种加载状态可以帮助防止过早地渲染内容,并提供更好的用户体验。

以下是您可以重构代码以包含加载状态的方法:

export const RequireAuth = ({ children }: { children: JSX.Element }) => {
  const auth = useAuth(); // 通过Auth Context使用的钩子
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const checkAuth = async () => {
      if (!auth.user) {
        setIsLoading(false);
      }
    };
    checkAuth();
  }, [auth.user]);

  if (isLoading) {
    return <LoadingSpinner />; // 渲染加载中的旋转图标或指示器
  }

  if (!auth.user) {
    return <Navigate to="/login" />;
  }

  return children;
};

通过这种方法:

  1. 我们将isLoading初始化为true,以指示身份验证验证过程正在进行中。
  2. useEffect钩子内部,我们检查用户是否已通过身份验证。如果没有,则将isLoading设置为false
  3. isLoadingtrue时,我们渲染加载中的旋转图标或指示器,以向用户提供反馈,表明后台正在处理某些操作。
  4. 一旦身份验证验证过程完成并且isLoading变为false,我们根据用户是否经过身份验证来渲染适当的内容。

通过使用加载状态,您可以确保组件正确渲染,并在身份验证验证等异步操作期间向用户提供更好的反馈。

2024-02-27