/** @jsxRuntime automatic */ /* sample-component.tsx: React components written in TypeScript with JSX. Free sample from 99helpers.com/file-types/tsx Set up: npm install react react-dom @types/react @types/react-dom Run: npx tsx sample-component.tsx (prints the HTML it renders) bun sample-component.tsx Check: npx tsc --noEmit --jsx react-jsx sample-component.tsx The first comment picks the automatic JSX runtime for this one file. Projects usually set it once in tsconfig.json ("jsx": "react-jsx"); without either, esbuild and tsx fall back to React.createElement() and the file fails with "React is not defined". */ // 1. Imports. With the automatic JSX runtime you don't import React to // use JSX; you import only the hooks and types you need. import { useState, type MouseEvent, type ReactNode } from "react"; import { renderToStaticMarkup } from "react-dom/server"; // 2. Props are described with an interface, so every is checked: // a missing label or an unknown tone is a compile error. interface BadgeProps { label: string; tone?: "info" | "warning"; children?: ReactNode; } // 3. A function component: it takes props and returns JSX. function Badge({ label, tone = "info", children }: BadgeProps) { // 4. JSX: lowercase tags are HTML elements, attributes use their DOM // names (className, not class), and {braces} hold JavaScript. return ( {label} {children} ); } // 5. A generic component. In a .tsx file an arrow function's type // parameter needs a trailing comma, : a bare would be read // as the start of a JSX tag. const List = ({ items, render }: { items: readonly T[]; render: (item: T) => ReactNode }) => (
    {items.map((item, index) => ( // 6. A key lets React match list items between renders.
  • {render(item)}
  • ))}
); // 7. State with an explicit type, and a typed event handler. function Counter({ start }: { start: number }) { const [count, setCount] = useState(start); function handleClick(event: MouseEvent) { event.currentTarget.blur(); setCount((previous) => previous + 1); } return ( ); } // 8. Type assertions in .tsx files use `as`. The older value form // is a syntax error here, because it looks like a JSX tag. const menu = JSON.parse('{"title":"Café menu","items":["Thé vert","Crème brûlée"]}') as { title: string; items: string[]; }; // 9. Conditional rendering, and a fragment <>… that groups elements // without adding one to the page. function App() { return ( <>

{menu.title}

{menu.items.length > 0 ? ( } /> ) : (

Nothing on the menu yet.

)} {" until 22:00"} ); } // 10. Render to an HTML string, so this file runs in a terminal. In a // browser app you would call createRoot(element).render() // from "react-dom/client" instead. console.log(renderToStaticMarkup());