iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Remix Intro

Remix (now React Router 7 framework mode) doubles down on the web platform - forms, loaders, nested routes, progressive enhancement.

Remix essentials

EXAMPLE
// 1. Scaffold
// npx create-remix@latest myapp

// app/routes/_index.tsx - route with loader + action
import { json, type LoaderFunctionArgs, type ActionFunctionArgs } from '@remix-run/node';
import { useLoaderData, Form, useNavigation } from '@remix-run/react';

export async function loader({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);
  const q = url.searchParams.get('q') || '';
  const users = await db.users.find({ name: { $regex: q, $options: 'i' } }).toArray();
  return json({ users, q });
}

export async function action({ request }: ActionFunctionArgs) {
  const fd = await request.formData();
  const id = String(fd.get('id'));
  await db.users.deleteOne({ _id: id });
  return null;
}

export default function Index() {
  const { users, q } = useLoaderData<typeof loader>();
  const nav = useNavigation();
  return (
    <div>
      <Form method='get'>
        <input type='search' name='q' defaultValue={q} />
        <button type='submit'>Search</button>
      </Form>
      {nav.state === 'loading' && <p>loading...</p>}
      <ul>
        {users.map((u) => (
          <li key={u._id}>
            {u.name}
            <Form method='post' style={{ display: 'inline' }}>
              <input type='hidden' name='id' value={u._id} />
              <button>delete</button>
            </Form>
          </li>
        ))}
      </ul>
    </div>
  );
}

// 2. Nested routes
// app/routes/users.tsx        - parent
// app/routes/users.$id.tsx     - child
// Parent uses <Outlet /> to render the child.

// 3. Error boundaries per route
export function ErrorBoundary() {
  return <div>Something went wrong.</div>;
}

// 4. Streaming with defer
import { defer } from '@remix-run/node';
import { Await, useLoaderData } from '@remix-run/react';
import { Suspense } from 'react';

export async function loader() {
  return defer({
    fast: await getStats(),
    slow: getRecentActivity(),     // not awaited
  });
}

export default function() {
  const { fast, slow } = useLoaderData<typeof loader>();
  return (
    <div>
      <p>Active: {fast.active}</p>
      <Suspense fallback={<p>loading activity...</p>}>
        <Await resolve={slow}>{(list) => <List items={list} />}</Await>
      </Suspense>
    </div>
  );
}

// 5. Deploy
// Vercel, Netlify, Cloudflare Pages, Fly, AWS Amplify - all have Remix targets.
// Choose based on edge needs vs Node features (e.g. crypto, fs).

Why it matters

Remix is the bet on the web platform - Forms, URLs, and HTTP responses as the primary API. Loaders + actions remove the data-fetching boilerplate; nested routes give you UI structure. Choose Remix when SEO and forms matter; choose Next when RSC + Vercel does.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Remix route
export function loader() { return { msg: 'hi' }; }
export default function Index() { const { msg } = useLoaderData(); return <h1>{msg}</h1>; }
Try it Yourself »

Discussion

Loading…