S
SolidJS8mo ago
미기

SolidStart error on redirect

Hello, I'm a newcomer to SolidJS and SolidStart. I am trying to redirect from one page to another, but it gives me an error while I do return redirect("/inquiry/" + form.get("personalCode"));. The site loads well if I refresh the page or go to the page directly. The Error
Internal Server Error (Make sure your app is wrapped in a <Router />)

This error happened inside a server function and you didn't handle it. So the client will receive an Internal Server Error. You can catch the error and throw a ServerError that makes sense for your UI. In production, the user will have no idea what the error is:

Error: Make sure your app is wrapped in a <Router />
at Module.invariant (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/utils.js:33:15)
at useRouter (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/routing.js:18:47)
at useRoute (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/routing.js:21:90)
at Module.useParams (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/routing.js:54:25)
at Object.$$serverHandler0 (/Users/mingeon/Algorix/evis-solid/src/routes/inquiry/[code].tsx:30:47)
at execute (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/server-functions/server.ts:189:37)
at Object.fn (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/server-functions/server.ts:201:12)
at Module.handleServerRequest (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/server-functions/server.ts:164:34)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async eval (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/middleware.ts:39:30)
at async eval (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/api/middleware.ts:40:12)
at async eval (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/entry-server/StartServer.tsx:45:12)
at async devFetch (file:///Users/mingeon/Algorix/evis-solid/node_modules/solid-start/dev/server.js:111:12)
at async startHandler (file:///Users/mingeon/Algorix/evis-solid/node_modules/solid-start/dev/server.js:134:20)
Internal Server Error (Make sure your app is wrapped in a <Router />)

This error happened inside a server function and you didn't handle it. So the client will receive an Internal Server Error. You can catch the error and throw a ServerError that makes sense for your UI. In production, the user will have no idea what the error is:

Error: Make sure your app is wrapped in a <Router />
at Module.invariant (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/utils.js:33:15)
at useRouter (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/routing.js:18:47)
at useRoute (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/routing.js:21:90)
at Module.useParams (/Users/mingeon/Algorix/evis-solid/node_modules/@solidjs/router/dist/routing.js:54:25)
at Object.$$serverHandler0 (/Users/mingeon/Algorix/evis-solid/src/routes/inquiry/[code].tsx:30:47)
at execute (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/server-functions/server.ts:189:37)
at Object.fn (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/server-functions/server.ts:201:12)
at Module.handleServerRequest (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/server-functions/server.ts:164:34)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async eval (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/server/middleware.ts:39:30)
at async eval (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/api/middleware.ts:40:12)
at async eval (/Users/mingeon/Algorix/evis-solid/node_modules/solid-start/entry-server/StartServer.tsx:45:12)
at async devFetch (file:///Users/mingeon/Algorix/evis-solid/node_modules/solid-start/dev/server.js:111:12)
at async startHandler (file:///Users/mingeon/Algorix/evis-solid/node_modules/solid-start/dev/server.js:134:20)
personal_code.tsx(origin)
import { Show } from "solid-js";
import { createRouteAction, redirect } from "solid-start";

export default function PersonalCode() {
const [loading, { Form }] = createRouteAction(async (form: FormData) => {
if (!form.get("personalCode")) {
throw "개인번호를 입력해주세요.";
}
return redirect("/inquiry/" + form.get("personalCode"));
});
return (
<main class="bg-gray-100">
<div class="min-h-screen flex items-center justify-center">
<div class="bg-white rounded-lg p-10 shadow-md">
<h1 class="text-3xl font-bold mb-6">EVIS: 고사장 조회 시스템</h1>
<Form>
<label class="block mb-2">조회용 개인번호</label>
<input name="personalCode" class="block w-full mb-4 p-2 border border-gray-300 rounded" type="text" disabled={loading.pending}/>
<button class="w-full py-3 px-6 text-center font-semibold text-white rounded-lg bg-blue-500" type="submit" disabled={loading.pending}>
조회하기
</button>
<Show when={loading.error}>
<p class="text-red-500 mt-4 text-sm">{loading.error}</p>
</Show>
</Form>
</div>
</div>
</main>
)
}
import { Show } from "solid-js";
import { createRouteAction, redirect } from "solid-start";

export default function PersonalCode() {
const [loading, { Form }] = createRouteAction(async (form: FormData) => {
if (!form.get("personalCode")) {
throw "개인번호를 입력해주세요.";
}
return redirect("/inquiry/" + form.get("personalCode"));
});
return (
<main class="bg-gray-100">
<div class="min-h-screen flex items-center justify-center">
<div class="bg-white rounded-lg p-10 shadow-md">
<h1 class="text-3xl font-bold mb-6">EVIS: 고사장 조회 시스템</h1>
<Form>
<label class="block mb-2">조회용 개인번호</label>
<input name="personalCode" class="block w-full mb-4 p-2 border border-gray-300 rounded" type="text" disabled={loading.pending}/>
<button class="w-full py-3 px-6 text-center font-semibold text-white rounded-lg bg-blue-500" type="submit" disabled={loading.pending}>
조회하기
</button>
<Show when={loading.error}>
<p class="text-red-500 mt-4 text-sm">{loading.error}</p>
</Show>
</Form>
</div>
</div>
</main>
)
}
(continuing below)
4 Replies
미기
미기8mo ago
inquiry/[code].tsx(destination)
import { Show, For } from "solid-js";
import { useParams, useRouteData } from "solid-start";
import { createServerData$ } from "solid-start/server";
import { db } from "~/db";

export function routeData() {
const data = createServerData$(async () => {
const personal_code = useParams().code;
const data = await db.examroom.findMany({
where: {
code: personal_code,
},
});
data.sort((a, b) => {
if (a.date < b.date) {
return -1;
}
if (a.date > b.date) {
return 1;
}
if (a.period < b.period) {
return -1;
}
if (a.period > b.period) {
return 1;
}
return 0;
});
const final_data = {
data: data,
message: "조회된 고사장 정보입니다.",
};
return final_data;
});
return data;
}

export default function Inquiry() {
const data = useRouteData();
const personal_code = useParams().code;
return (
<main class="bg-gray-100 min-h-screen">
<div class="container mx-auto py-12">
<div class="bg-white p-8 rounded-xl shadow-md">
<h1 class="text-3xl font-bold mb-8">고사장 통합 조회 시스템</h1>
<div id="data-container" class="space-y-4">
<Show when={data()}>
<Show when={data().message} fallback={
<p class="text-red-500 text-sm">알 수 없는 오류가 발생했습니다.</p>
}>
<p>학생 코드: {personal_code}</p>
<Show when={data().data.length > 0} fallback={
<p class="text-red-500">조회된 고사장 정보가 없습니다.</p>
}>
<p>{data().message}</p>
<table class="border table-auto text-center border-gray-700">
<thead class="border border-gray-700">
<tr>
<th class="px-8">과목</th>
<th class="px-8">고사장</th>
<th class="px-8">시험일</th>
<th class="px-8">시험 시간</th>
</tr>
</thead>
<tbody>
<For each={data().data}>
{(item) => (
<tr>
<td class="px-8">{item.subject}</td>
<td class="px-8">{item.room}</td>
<td class="px-8">{item.date}</td>
<td class="px-8">{item.period}교시</td>
</tr>
)}
</For>
</tbody>
</table>
</Show>
</Show>
</Show>
</div>
</div>
</div>
<footer class="w-full py-4 text-center text-xs text-gray-600">
Disclaimer : 본 서비스는 참고용으로만 이용해주시길 바라며, 잘못된 정보에 대하여 책임지지 않습니다.
</footer>
</main>
)
}
import { Show, For } from "solid-js";
import { useParams, useRouteData } from "solid-start";
import { createServerData$ } from "solid-start/server";
import { db } from "~/db";

export function routeData() {
const data = createServerData$(async () => {
const personal_code = useParams().code;
const data = await db.examroom.findMany({
where: {
code: personal_code,
},
});
data.sort((a, b) => {
if (a.date < b.date) {
return -1;
}
if (a.date > b.date) {
return 1;
}
if (a.period < b.period) {
return -1;
}
if (a.period > b.period) {
return 1;
}
return 0;
});
const final_data = {
data: data,
message: "조회된 고사장 정보입니다.",
};
return final_data;
});
return data;
}

export default function Inquiry() {
const data = useRouteData();
const personal_code = useParams().code;
return (
<main class="bg-gray-100 min-h-screen">
<div class="container mx-auto py-12">
<div class="bg-white p-8 rounded-xl shadow-md">
<h1 class="text-3xl font-bold mb-8">고사장 통합 조회 시스템</h1>
<div id="data-container" class="space-y-4">
<Show when={data()}>
<Show when={data().message} fallback={
<p class="text-red-500 text-sm">알 수 없는 오류가 발생했습니다.</p>
}>
<p>학생 코드: {personal_code}</p>
<Show when={data().data.length > 0} fallback={
<p class="text-red-500">조회된 고사장 정보가 없습니다.</p>
}>
<p>{data().message}</p>
<table class="border table-auto text-center border-gray-700">
<thead class="border border-gray-700">
<tr>
<th class="px-8">과목</th>
<th class="px-8">고사장</th>
<th class="px-8">시험일</th>
<th class="px-8">시험 시간</th>
</tr>
</thead>
<tbody>
<For each={data().data}>
{(item) => (
<tr>
<td class="px-8">{item.subject}</td>
<td class="px-8">{item.room}</td>
<td class="px-8">{item.date}</td>
<td class="px-8">{item.period}교시</td>
</tr>
)}
</For>
</tbody>
</table>
</Show>
</Show>
</Show>
</div>
</div>
</div>
<footer class="w-full py-4 text-center text-xs text-gray-600">
Disclaimer : 본 서비스는 참고용으로만 이용해주시길 바라며, 잘못된 정보에 대하여 책임지지 않습니다.
</footer>
</main>
)
}
미기
미기8mo ago
root.tsx
// @refresh reload
import { Suspense } from "solid-js";
import {
Body,
ErrorBoundary,
FileRoutes,
Head,
Html,
Meta,
Routes,
Scripts,
Title,
} from "solid-start";
import "./root.css";

export default function Root() {
return (
<Html lang="ko">
<Head>
<Title>고사장 통합 조회 시스템</Title>
<Meta charset="utf-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<Body>
<ErrorBoundary>
<Suspense fallback={<div>Loading</div>}>
<Routes>
<FileRoutes />
</Routes>
</Suspense>
</ErrorBoundary>
<Scripts />
</Body>
</Html>
);
}
// @refresh reload
import { Suspense } from "solid-js";
import {
Body,
ErrorBoundary,
FileRoutes,
Head,
Html,
Meta,
Routes,
Scripts,
Title,
} from "solid-start";
import "./root.css";

export default function Root() {
return (
<Html lang="ko">
<Head>
<Title>고사장 통합 조회 시스템</Title>
<Meta charset="utf-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<Body>
<ErrorBoundary>
<Suspense fallback={<div>Loading</div>}>
<Routes>
<FileRoutes />
</Routes>
</Suspense>
</ErrorBoundary>
<Scripts />
</Body>
</Html>
);
}
vite.config.ts
import solid from "solid-start/vite";
import { defineConfig } from "vite";
import vercel from "solid-start-vercel";

export default defineConfig({
plugins: [solid({
ssr: true,
adapter: vercel() })],
ssr: { external: ["@prisma/client"] },
});
import solid from "solid-start/vite";
import { defineConfig } from "vite";
import vercel from "solid-start-vercel";

export default defineConfig({
plugins: [solid({
ssr: true,
adapter: vercel() })],
ssr: { external: ["@prisma/client"] },
});
directory
.
├── README.md
├── bun.lockb
├── dummy.ts
├── package.json
├── postcss.config.js
├── prisma
│ ├── migrations
│ │ ├── 20231024111618_init
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ └── schema.prisma
├── public
├── src
│ ├── db
│ │ └── index.ts
│ ├── entry-client.tsx
│ ├── entry-server.tsx
│ ├── global.d.ts
│ ├── root.css
│ ├── root.tsx
│ └── routes
│ ├── [...404].tsx
│ ├── index.tsx
│ ├── inquiry
│ │ └── [code].tsx
│ ├── intranet.tsx
│ └── personal_code.tsx
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts

9 directories, 22 files
.
├── README.md
├── bun.lockb
├── dummy.ts
├── package.json
├── postcss.config.js
├── prisma
│ ├── migrations
│ │ ├── 20231024111618_init
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ └── schema.prisma
├── public
├── src
│ ├── db
│ │ └── index.ts
│ ├── entry-client.tsx
│ ├── entry-server.tsx
│ ├── global.d.ts
│ ├── root.css
│ ├── root.tsx
│ └── routes
│ ├── [...404].tsx
│ ├── index.tsx
│ ├── inquiry
│ │ └── [code].tsx
│ ├── intranet.tsx
│ └── personal_code.tsx
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts

9 directories, 22 files
repository: https://github.com/issac4892/EVIS-solidstart
GitHub
GitHub - issac4892/EVIS-solidstart
Contribute to issac4892/EVIS-solidstart development by creating an account on GitHub.
미기
미기8mo ago
thanks But I still get the same error about <Router /> There is <Routes><FileRoutes /></Routes> in root.tsx not not router. Can this be a problem? Maybe can this be a bug?
MyWay
MyWay8mo ago
did you solve?