渲染不同步

问题描述 投票:0回答:1

我对以下代码有一个问题,这让我发疯。

简而言之,我想做的是:

- 将 sessionStorage 中保存的 JWT 令牌保存为登录成功时的状态。

- 在状态中保存布尔值 isTokenValid。

- 通过对 /api/validateToken 端点的 GET 请求检查令牌是否有效并相应地设置 isTokenValid。

- 如果令牌有效 (isTokenValid = true) --> 显示仪表板

- 如果令牌无效(TokenValid = false)--> 显示错误页面

  • App.jsx

    import './styles/Reset.css';
    import './styles/App.css';
    import 'bootstrap/dist/css/bootstrap.min.css';
    
    import React from 'react';
    import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
    import axios from 'axios';
    
    import Home from './components/Home';
    import Header from './components/Header';
    import Footer from './components/Footer';
    import Login from './components/Login';
    import Signup from './components/Signup';
    import Dashboard from './components/Dashboard';
    import FailedAuth from './components/FailedAuth';
    
    function App() {
    
      const [token, setToken] = React.useState(sessionStorage.getItem('token'));
      const [isTokenValid, setIsTokenValid] = React.useState(false);
      const [loading, setLoading] = React.useState(true);
    
      async function validateToken() {
        try {
          const response = await axios.get('http://localhost:5000/api/validateToken', { 
            headers: { 
              'Authorization': `Bearer ${token}` 
            } 
          });
    
          if (response.status === 200) {
            setIsTokenValid(true);
          } else {
            setIsTokenValid(false);
          }
        } catch (error) {
          setIsTokenValid(false);
        } finally {
          setLoading(false);
        }
      }
    
      React.useEffect(() => {
        async function fetchData() {
          if (token) {
            await validateToken();
          }
        }
    
        fetchData();
      });
    
      if (loading) {
        return (
          <div className="loading">
            <div className="spinner-border text-primary" role="status">
              <span className="visually-hidden">Loading...</span>
            </div>
          </div>
        );
      }
    
      return (
        <Router>
            <Routes>
              <Route path="/login/*" element={
                <>
                  <Header type="auth" />
                  <Login />
                </>
              }
              />
              <Route path="/signup/*" element={
                <>
                  <Header type="auth" />
                  <Signup />
                </>
              }
              />
              <Route path="/*" element={
                <>
                  <Header type="home" />
                  <Home />
                  <Footer />
                </>
                }
              />
              <Route path="/dashboard/*" element={
                <>
                  {isTokenValid ? <Dashboard /> : <FailedAuth />}
                </>
              }
              />
            </Routes>
        </Router>
      );
    
    }
    
    export default App;
    
  • 服务器.js

    app.get('/api/validateToken', passport.authenticate('jwt', { session: false }), (req, res) => {
        try {
            res.status(200).json({ message: 'Token is valid' });
        } catch (error) {
            res.status(500).json({ error: error.message });
        }
    });
    

服务器完美地处理身份验证,并且 JWT 令牌已正确分配。

我的问题恰恰在于 isTokenValid 条件下的路由渲染。

当用户登录时,它会呈现到仪表板,即使令牌有效,它也会立即显示 ,但如果我刷新页面,它会显示 ,因为它应该是这样。

令牌过期后,总是显示,所以没有问题,它做了它应该做的事情。

我认为这是一个同步问题,但我不确定(我对React还是新手,这是我的第一个项目)。

有人可以帮助我吗?这样当我发现自己面临同样的情况时,我知道如何行事。

reactjs express authentication jwt token
1个回答
0
投票

问题

如果您不提供依赖项数组,则 useEffect 挂钩将在每次渲染后运行。它正在创建一个无限循环,因为您通过设置 isTokenValid 和 isLoading 状态重新渲染。

解决方案

[token]

 添加到 useEffect 挂钩作为依赖项数组。

useEffect(() => { async function fetchData() { if (token) { await validateToken(); } } fetchData(); }, [token]);
    
© www.soinside.com 2019 - 2024. All rights reserved.