1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React, { createContext, useState } from "react";
3import { BrowserRouter, Link, Navigate, Outlet, Route, Routes, useLocation } from "react-router";
4import { useLocalStorage } from "react-use";
5import { useUser } from "../hooks/useUser.tsx";
6import { ChatRoute } from "./ChatRoute.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useEffect, useMemo, useState } from "https://esm.sh/react@18.2.0";
3
4const BRAND_COLORS = {
1# React Router Hono Starter
2
3Minimal React Router + Hono starter example in ["data mode"][modes] with server-side rendering for Val Town
4
5[View demo][demo]
7## How it works
8
9The `server.tsx` file is the main server that responds with an HTML stream, using React Router, or an API response.
10The HTML includes a `<script type="module">` tag that loads the `client.tsx` file to hydrate the app
11with client-side routing provided by React Router in "data mode".
12
13The routes are defined in `routes` and can include data loading and actions.
15The About page uses the `useLoaderData` hook to render the data from the loader in the page.
16
17[demo]: https://react-router-hono.val.run
18
19[View more starters][how-to]
20
21[how-to]: https://val.town/x/jxnblk/how-to
22[modes]: https://reactrouter.com/start/modes
1/** @jsxImportSource https://esm.sh/react@19 */
2import { Hono } from "npm:hono@4";
3import * as React from "https://esm.sh/react@19";
4import ReactDOMServer from "https://esm.sh/react-dom@19/server";
5import {
6 createStaticHandler,
7 createStaticRouter,
8 StaticRouterProvider,
9} from "https://esm.sh/react-router";
10import routes from "./routes.tsx";
11
22});
23
24// react app
25app.get("*", async (c) => {
26 const { query, dataRoutes } = createStaticHandler(routes);
28 const router = createStaticRouter(dataRoutes, context);
29
30 let html = await ReactDOMServer.renderToReadableStream(
31 <StaticRouterProvider
32 router={router}
1import { ActionFunctionArgs, redirect } from "https://esm.sh/react-router@7.5.0?deps=react@18.2.0,react-dom@18.2.0";
2import { createTopic } from "../backend/database/queries.ts";
3
1import { LoaderFunctionArgs } from "https://esm.sh/react-router@7.5.0?deps=react@18.2.0,react-dom@18.2.0";
2import { search } from "../backend/database/queries.ts";
3
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useEffect } from "https://esm.sh/react@18.2.0";
3import { Link, useLoaderData, useParams } from "https://esm.sh/react-router@7.5.0?deps=react@18.2.0,react-dom@18.2.0";
4import { Message, Topic } from "../shared/types.ts";
5import { MessageForm } from "../frontend/components/MessageForm.tsx";
1import { LoaderFunctionArgs } from "https://esm.sh/react-router@7.5.0?deps=react@18.2.0,react-dom@18.2.0";
2import { getTopicById, getMessagesByTopicId } from "../backend/database/queries.ts";
3
1import { LoaderFunctionArgs } from "https://esm.sh/react-router@7.5.0?deps=react@18.2.0,react-dom@18.2.0";
2import { getTopicById, getMessageById, getMessagesByTopicId } from "../backend/database/queries.ts";
3
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from "https://esm.sh/react@18.2.0";
3import { Form, useNavigation, useSearchParams } from "https://esm.sh/react-router@7.5.0?deps=react@18.2.0,react-dom@18.2.0";
4import { LoadingSpinner } from "./LoadingSpinner.tsx";
5