===== React ===== React integration with Litestar Vite provides a modern development experience with Hot Module Replacement (HMR) and optimized production builds. Quick Start ----------- .. code-block:: bash litestar assets init --template react This creates a React 18+ project with TypeScript support. Project Structure ----------------- React applications use **SPA mode** - Vite serves the ``index.html`` directly: .. code-block:: text my-app/ ├── app.py # Litestar backend (API only) ├── index.html # Vite entry point (root level) ├── package.json ├── vite.config.ts ├── tsconfig.json └── src/ ├── main.tsx # React entry point ├── App.tsx # Root component └── app.css Backend Setup ------------- In SPA mode, Litestar serves only your API endpoints. The VitePlugin handles serving the frontend automatically: .. literalinclude:: /../examples/react/app.py :language: python :start-after: # [docs-start:spa-vite-config] :end-before: # [docs-end:spa-vite-config] :caption: examples/react/app.py Key points: - ``mode="spa"`` tells Vite to serve ``index.html`` for non-API routes - No ``template_config`` needed - Jinja is not used in SPA mode - ``TypeGenConfig()`` enables TypeScript type generation from OpenAPI Vite Configuration ------------------ .. literalinclude:: /../examples/react/vite.config.ts :language: typescript :caption: vite.config.ts Key configuration: - ``input`` - Entry point(s) for your application - ``resourceDir`` - Source directory (explicitly set to ``src``) - The plugin auto-reads ``assetUrl``, ``bundleDir`` from ``.litestar.json`` (generated by Python) HTML Entry Point ---------------- In SPA mode, ``index.html`` lives at the project root and uses standard Vite syntax: .. literalinclude:: /../examples/react/index.html :language: html :caption: index.html .. note:: Unlike template mode, SPA mode doesn't use Jinja helpers like ``{{ vite() }}``. Vite processes the HTML directly. React Component --------------- .. code-block:: tsx import { useState, useEffect } from "react"; function App() { const [message, setMessage] = useState(""); useEffect(() => { fetch("/api/summary") .then((res) => res.json()) .then((data) => setMessage(data.headline)); }, []); return (
{message}