Updating and Deleting Users

User Update and Deletion API Exploration

Welcome back! Now that you can create users with POST, it’s time to explore what it looks like to modify and remove users from an API. Updating and deleting are two of the most common backend operations—and they come with some new considerations like “What if the user doesn’t exist?” and “What should we return when deletion succeeds?”

In this lesson, you’ll work with the dynamic user route app/routes/api.users.$id.tsx, which handles requests like /api/users/3. You’ll see how Remix uses loader() to fetch a single user by ID, and how action() can support multiple mutation methods—in this case, PUT (replace/update) and DELETE (remove). Finally, you’ll connect that behavior to the UI in app/routes/_index.tsx, focusing on handleReplace() and handleDelete().

The dynamic user route: /api/users/:id

This project uses a separate file for “single-user” operations: app/routes/api.users.$id.tsx.

  • The $id in the filename is Remix’s dynamic segment syntax.

  • A request to /api/users/5 will land in this file, and Remix will provide params.id to your route handlers.

  • This route supports:

    • GET /api/users/:id via loader()
    • PUT /api/users/:id via action()
    • DELETE /api/users/:id via action()

Fetching a user by ID with the loader

This loader() is responsible for looking up one user by ID and returning either the user object or a 404 if it doesn’t exist. The code below lives in app/routes/api.users.$id.tsx.

TSX
// app/routes/api.users.$id.tsx
import { json, type LoaderFunctionArgs, type ActionFunctionArgs } from '@remix-run/node';
import { users } from '~/lib/data';

export async function loader({ params }: LoaderFunctionArgs) {
  const userId = parseInt(params.id!, 10);
  const user = users.find((u) => u.id === userId);

  if (!user) {
    return json({ error: 'User not found' }, { status: 404 });
  }
  return json(user);
}
  • params.id comes from the URL segment in /api/users/:id. The parseInt(..., 10) converts it into a number so it can be compared against numeric user.id values.
  • users.find(...) searches the in-memory array for the first matching ID. This is a simple stand-in for what would be a database query in a real app.
  • Returning a 404 with { error: 'User not found' } is important: it tells clients the resource doesn’t exist (as opposed to a generic “bad request”).
  • When the user exists, the response is json(user)—again, this route returns the raw object, not a wrapped { user: ... } payload.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal