You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中Private Route登录后无法跳转至Dashboard问题求助

问题描述

直接访问http://localhost:3001/dashboard时,页面能正确跳转到/signin;但使用正确账号登录后,路由未切换至/dashboard,仍停留在/signin。服务器连接正常,当前仅支持单用户登录,需排查问题原因。


主App代码片段(所有库已正确导入)

useEffect(() => {
    fetch('http://localhost:3000')
        .then((response) => response.json())
        .then(console.log)
})

const [user, setUser] = useState(false);
const isUserValid = (user) => {
    setUser(user);
}

return (
    <Routes>
        <Route path="/signin" element={<Signin userValue={isUserValid} />} />
        <Route path="/register" element={<Register />} />
        <Route path="/dashboard" element={<PrivateRoute userValid={user} />}>
            <Route element={<Dashboard />} path="/dashboard" />
        </Route>
    </Routes>
)

服务器代码(Node.js + express.json + cors)

app.post('/signin', (req, res) => {
    if(req.body.email === database.users[0].email &&
        req.body.password === database.users[0].password){
        res.json('success');
    } else {
        res.status(400).json('error');
    }
})

Private Route模块代码

const PrivateRoute = ({children, userValid}) => {
   return userValid ? children : <Navigate to="/signin" />;
}

export default PrivateRoute;

Signin模块代码(表单可正常获取输入值并与服务器交互)

const Signin = ({userValue}) => {
    const [userEmail, setUserEmail] = useState('');
    const [userPassword, setUserPassword] = useState('');
  
    const onEmailChange = (event) => {
      setUserEmail(event.target.value);
    }
  
    const onPasswordChange = (event) => {
      setUserPassword(event.target.value);
    }
  
    const onSubmitSignIn = () => {
      fetch('http://localhost:3000/signin', {
        method: 'post',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
          email: userEmail,
          password: userPassword
        })
      })
        .then(response => response.json())
        .then(data => {
            if(data === 'success'){
                userValue(true);
                window.location.href = "/dashboard";
            }
        })
    }

问题原因及修复方案

1. 页面刷新导致登录状态丢失

登录成功后用window.location.href = "/dashboard"会触发全页面刷新,App组件的user状态会被重置为初始值false,PrivateRoute检测到未登录,就会再次跳回/signin。

修复:改用React Router的useNavigate钩子跳转,避免页面刷新:

// 在Signin组件中导入useNavigate
import { useNavigate } from 'react-router-dom';

// 组件内初始化navigate
const navigate = useNavigate();

// 替换window.location.href为
navigate('/dashboard');

2. 嵌套路由路径配置错误

当前Dashboard子路由的路径写为/dashboard,会和父路由的/dashboard重复,最终路径变成/dashboard/dashboard,导致路由不匹配。

修复:将子路由路径改为相对路径"":

<Route path="/dashboard" element={<PrivateRoute userValid={user} />}>
    <Route element={<Dashboard />} path="" />
</Route>

或者简化路由结构,直接把Dashboard作为PrivateRoute的子元素:

<Route path="/dashboard" element={<PrivateRoute userValid={user}><Dashboard /></PrivateRoute>} />

可选优化:登录状态持久化

页面刷新后user状态会丢失,可将状态存入localStorage,在App初始化时读取:

// App组件中修改useState初始化
const [user, setUser] = useState(() => {
    return localStorage.getItem('isLoggedIn') === 'true';
});

// 修改isUserValid函数
const isUserValid = (isLoggedIn) => {
    setUser(isLoggedIn);
    localStorage.setItem('isLoggedIn', isLoggedIn.toString());
}

内容的提问来源于stack exchange,提问作者Norbert Dąbrowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:45:28