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

Solid JS路由条件渲染问题:基于登录状态控制路由组件显示

解决SolidJS中基于登录状态的路由条件渲染问题

你的当前写法存在几个核心问题:

  • 每个路由重复判断登录状态,代码冗余且易出错
  • 直接通过component属性切换组件,Solid的响应式更新逻辑会导致路由匹配混乱,出现渲染异常
  • 缺少合理的重定向逻辑,未登录访问私有路由、已登录访问登录页时的跳转行为不清晰

以下是更规范且可维护的实现方案:

1. 封装私有路由组件

创建一个ProtectedRoute组件,统一处理登录校验和重定向逻辑,避免重复代码:

import { Route, Navigate } from "@solidjs/router";

type ProtectedRouteProps = {
  children: JSX.Element;
  user: unknown; // 根据你的user类型调整
  loading?: boolean; // 可选,处理异步加载状态
};

export function ProtectedRoute({ children, user, loading }: ProtectedRouteProps) {
  // 处理异步加载中的状态
  if (loading) {
    return <div>加载中...</div>; // 替换为你的加载组件
  }

  // 未登录时重定向到登录页,携带当前路径用于登录后跳转
  if (!user) {
    return <Navigate href={`/login?redirect=${window.location.pathname}`} />;
  }

  return children;
}

2. 重构路由结构

将公开路由(未登录可访问)和私有路由(需登录)分开,用嵌套路由整理层级,让结构更清晰:

import { Router, Route, Navigate } from "@solidjs/router";
import { ProtectedRoute } from "./ProtectedRoute";
// 导入你的页面组件:HomeScreen、LoginScreen、InventoryScreen等

export const App = () => {
  const [authAccount] = useAuth();
  const { user, token, loading } = authAccount.auth;

  return (
    <Router>
      {/* 公开路由:未登录可访问,已登录自动跳首页 */}
      <Route path="/login">
        {!loading && (!user ? <LoginScreen /> : <Navigate href="/" />)}
      </Route>
      <Route path="/register">
        {!loading && (!user ? <RegistrationScreen /> : <Navigate href="/" />)}
      </Route>
      <Route path="/fp">
        {!loading && (!user ? <ForgotPasswordScreen /> : <Navigate href="/" />)}
      </Route>

      {/* 私有路由:需登录才能访问 */}
      <Route path="/">
        <ProtectedRoute user={user} loading={loading}>
          <Route path="/" component={HomeScreen} />
          
          {/* 库存相关子路由 */}
          <Route path="/inventory">
            <Route path="/" component={InventoryScreen} />
            <Route path="/:itemID" component={ViewItemScreen} />
            <Route path="/add" component={AddItemScreen} />
            <Route path="/edit/:itemID" component={EditItemScreen} />
          </Route>
          
          {/* 交易相关子路由 */}
          <Route path="/transaction">
            <Route path="/" component={TransactionScreen} />
            <Route path="/:transactionID" component={ViewTransactionScreen} />
            <Route path="/edit/:transactionID" component={EditTransactionScreen} />
            <Route path="/add/in/:itemID?" component={TransactionInScreen} />
            <Route path="/add/out/:itemID?" component={TransactionOutScreen} />
            <Route path="/add/lent/:itemID?" component={TransactionLentScreen} />
            <Route path="/add/return/:itemID?" component={TransactionReturnScreen} />
          </Route>
          
          {/* 设置相关子路由 */}
          <Route path="/settings">
            <Route path="/" component={AccountSettingsScreen} />
            <Route path="/notifications" component={NotificationSettingsScreen} />
            <Route path="/password" component={PasswordSettingsScreen} />
          </Route>
          
          <Route path="/ran" component={RemindersAndNotificationScreen} />
        </ProtectedRoute>
      </Route>

      {/* 404 fallback:匹配所有未定义的路径 */}
      <Route path="*">
        <Navigate href="/" />
      </Route>
    </Router>
  );
};

3. 补充登录后的跳转逻辑

在LoginScreen中,登录成功后可以读取redirect参数,跳回用户原本想要访问的页面:

import { useSearchParams, useNavigate } from "@solidjs/router";

export function LoginScreen() {
  const searchParams = useSearchParams();
  const navigate = useNavigate();

  const handleLogin = async () => {
    // 执行登录逻辑...
    const redirectUrl = searchParams.redirect || "/";
    navigate(redirectUrl);
  };

  return (
    // 登录表单...
  );
}

关键优化点说明

  • 代码复用:通过ProtectedRoute统一处理权限校验,避免每个路由重复写判断逻辑
  • 路由清晰:嵌套路由让层级结构更直观,维护起来更方便
  • 状态处理:加入加载状态判断,避免在auth数据未加载完成时出现错误跳转
  • 用户体验:登录后跳回原路径,提升使用流畅度

内容的提问来源于stack exchange,提问作者Cozy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:57:02