使用SolidStart从服务器加载数据异常问题求助
问题分析与解决
核心错误:未正确访问Resource的响应式状态
你代码里的关键问题是直接访问data.state而非调用data.state()。SolidStart中createServerData$返回的是Resource对象,其state是一个响应式访问器(函数),必须通过调用它才能获取当前状态,同时让createEffect追踪状态变化。
因为你没有调用data.state(),createEffect无法感知状态从pending变为ready的变化,所以首次加载时只打印初始的pending,后续状态更新不会触发effect重新执行。而导航返回时是客户端路由重新触发数据请求,组件重新挂载的行为偶然让你看到了预期输出,但这不是正确的处理方式。
其他优化点
- 复用PrismaClient实例:每次调用
createServerData$都新建PrismaClient会导致数据库连接过多,应该全局复用实例。 - 移除不必要的信号:组件里的
users信号完全多余,直接使用useRouteData返回的data()即可获取数据。
修正后的代码
import { createServerData$ } from "solid-start/server"; import { PrismaClient } from "@prisma/client"; import { For, createEffect } from "solid-js"; import { useRouteData } from "solid-start"; // 全局复用PrismaClient实例 const prisma = new PrismaClient(); export function routeData(){ const users = createServerData$(async ()=>{ const allusers = await prisma.user.findMany(); console.log("all Users: ", allusers); // 全局实例无需每次断开连接,保持长连接更高效 return allusers; }); return users; } export default function Home(){ const [dataLoad, setDataLoad] = createSignal(false); const data = useRouteData<typeof routeData>(); createEffect(()=>{ // 正确调用state访问器函数,触发响应式追踪 const currentState = data.state(); console.log("Loading Status:"+ currentState); if(currentState !== 'ready') return; const userData = data(); if(userData === null){ console.log("No Data"); }else{ console.log("data loaded"); setDataLoad(true); console.log(JSON.stringify(userData)); // 用JSON.stringify打印对象,避免toString输出[object Object] } }); return ( <div> {dataLoad() ? ( <For each={data()}> {user => <div key={user.id}>{user.name}</div>} </For> ) : ( <p>Loading...</p> )} </div> ); }
修正后生效的原因
- 调用
data.state()后,createEffect会正确追踪状态变化,无论首次SSR加载还是客户端路由导航,状态从pending到ready的变化都会触发effect重新执行。 - 全局复用
PrismaClient避免了频繁创建/断开数据库连接的性能问题。 - 直接使用
data()获取数据,减少了不必要的信号嵌套,代码更简洁。
内容的提问来源于stack exchange,提问作者MetaphysX
相关产品推荐
相关产品推荐

