0Pricing
tRPC End-to-End Type Safe APIs · Leçon

Développement de procédures de mutation

Créez des procédures pour les opérations de création, de mise à jour et de suppression de données avec les procédures de mutation tRPC.

Développement de procédures de mutation est une leçon tRPC End-to-End Type Safe APIs gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage tRPC End-to-End Type Safe APIs, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours tRPC End-to-End Type Safe APIs comprend 4 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

What Are tRPC Mutations?

Welcome to tRPC mutation procedures! So far, you've likely used queries to fetch data, like getting a list of users or a single product.

But what if you need to change data? This is where mutations come in. Mutations are API operations designed to modify data on your server.

  • Create: Add new records (e.g., create a user).
  • Update: Modify existing records (e.g., update a user's email).
  • Delete: Remove records (e.g., delete a user).

They are the 'CUD' in CRUD operations!

Mutations vs. Queries

It's important to understand the difference between queries and mutations in tRPC:

  • Queries: Used for fetching data. They are typically read-only and should not have side effects (i.e., they don't change data on the server).
  • Mutations: Used for changing data. They are designed to have side effects and modify your server's state.

tRPC enforces this separation, helping you build more predictable and robust APIs. When you need to create, update, or delete anything, always reach for a mutation.

Defining a Simple Mutation

Let's start by defining a very simple mutation. Just like queries, mutations are procedures within your tRPC router.

We use .mutation() instead of .query(). This example takes a name as input and returns a greeting string.

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

const appRouter = t.router({
  sayHello: t.procedure
    .input(z.object({ name: z.string() }))
    .mutation(({ input }) => {
      // In a real app, this might save 'name' to a log
      return `Hello, ${input.name}!`;
    }),
});

export type AppRouter = typeof appRouter;
// This defines a valid tRPC router with one mutation.

Creating Data: The 'Create' Mutation

A common use case for mutations is creating new data. Let's build a createUser mutation that accepts a user's name and email.

We'll use zod (a schema validation library) to define the expected input structure. This ensures type safety and validates incoming data automatically.

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

interface User {
  id: string;
  name: string;
  email: string;
}
const users: User[] = []; // Our 'database'

const appRouter = t.router({
  createUser: t.procedure
    .input(z.object({
      name: z.string().min(1),
      email: z.string().email(),
    }))
    .mutation(({ input }) => {
      const newUser: User = {
        id: `user-${users.length + 1}`,
        name: input.name,
        email: input.email,
      };
      users.push(newUser); // Add to our fake database
      return newUser; // Return the new user object
    }),
});

export type AppRouter = typeof appRouter;
// This router defines how to create a user.

Updating Data: The 'Update' Mutation

Next, let's tackle updating existing data. An updateUser mutation will need the id of the user to update, plus the fields that need changing.

Notice how we can make fields .optional() in our Zod schema if they might not always be provided during an update.

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

interface User {
  id: string;
  name: string;
  email: string;
}
const users: User[] = [
  { id: 'user-1', name: 'Alice', email: 'alice@example.com' },
];

const appRouter = t.router({
  updateUser: t.procedure
    .input(z.object({
      id: z.string(),
      name: z.string().min(1).optional(),
      email: z.string().email().optional(),
    }))
    .mutation(({ input }) => {
      const userIndex = users.findIndex(u => u.id === input.id);
      if (userIndex === -1) {
        throw new Error('User not found');
      }
      // Merge existing data with new input
      users[userIndex] = { ...users[userIndex], ...input };
      return users[userIndex]; // Return the updated user
    }),
});

export type AppRouter = typeof appRouter;
// This router defines how to update a user.

Deleting Data: The 'Delete' Mutation

Finally, let's create a mutation to delete data. A deleteUser mutation typically only needs the id of the record to remove.

For the return value, you might send back a simple success message or the ID of the deleted item. Here, we'll return a boolean indicating success.

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

interface User {
  id: string;
  name: string;
  email: string;
}
const users: User[] = [
  { id: 'user-1', name: 'Alice', email: 'alice@example.com' },
  { id: 'user-2', name: 'Bob', email: 'bob@example.com' },
];

const appRouter = t.router({
  deleteUser: t.procedure
    .input(z.object({ id: z.string() }))
    .mutation(({ input }) => {
      const initialLength = users.length;
      const userIndex = users.findIndex(u => u.id === input.id);
      if (userIndex !== -1) {
        users.splice(userIndex, 1); // Remove from array
      }
      // Return true if an item was removed
      return { success: users.length < initialLength };
    }),
});

export type AppRouter = typeof appRouter;
// This router defines how to delete a user.

Client-Side Mutation Calls

Now that you've defined your mutations on the server, how do you call them from your frontend application?

Using the tRPC client, you simply access the mutation by its name and call the .mutate() method, passing your input data.

import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';

// A simplified AppRouter type for this client-side example.
// In a real app, you'd import 'AppRouter' from your shared types.
interface User { id: string; name: string; email: string; }
type AppRouter = {
  sayHello: (input: { name: string }) => Promise<string>;
  createUser: (input: { name: string; email: string }) => Promise<User>;
  deleteUser: (input: { id: string }) => Promise<{ success: boolean }>;
};

const trpc = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: 'http://localhost:3000/trpc', // Your tRPC server URL
    }),
  ],
});

async function runMutationCalls() {
  console.log('1. Calling sayHello...');
  const helloRes = await trpc.sayHello.mutate({ name: 'Coddy' });
  console.log(`Result: ${helloRes}`);

  console.log('2. Calling createUser...');
  const newUser = await trpc.createUser.mutate({
    name: 'Eve',
    email: 'eve@example.com',
  });
  console.log('Created:', newUser);

  console.log('3. Calling deleteUser...');
  const deleteRes = await trpc.deleteUser.mutate({ id: newUser.id });
  console.log('Deleted:', deleteRes.success);
}

runMutationCalls();
// This script simulates client-side mutation calls.

Handling Results and Errors

When you call a mutation from the client, it returns a Promise. You can use await to wait for the result, just like with any asynchronous operation.

For error handling, you can use standard JavaScript try...catch blocks around your .mutate() calls. tRPC will automatically propagate errors from your backend to the client.

try {
  const result = await trpc.createUser.mutate({ ... });
  // Handle success
} catch (error) {
  // Handle error
  console.error('Mutation failed:', error.message);
}

This makes error management straightforward and type-safe.

When to Use Mutations

Remember to use mutations for any operation that changes data on your server. This includes:

  • Submitting a form (e.g., user registration, posting a comment).
  • Toggling a setting (e.g., dark mode preference).
  • Performing administrative actions (e.g., banning a user).
  • Uploading files (though this can involve special handling).

By consistently using mutations for these actions, you maintain clarity, type safety, and leverage tRPC's powerful features for data modification.

Check Your Mutation Knowledge

You've learned how to define and use tRPC mutation procedures. Time for a quick check!

Recap: Mutation Procedures

Great job! In this lesson, you've mastered tRPC mutation procedures:

  • You learned that mutations are for operations that change data (Create, Update, Delete).
  • You saw how to define mutations using t.procedure.mutation() with input validation via Zod.
  • You built examples for creating, updating, and deleting data on the server.
  • You understood how to call these mutations from the client and handle their results.

Mutations are a core part of building interactive and data-driven applications with tRPC. Next, we'll explore input validation more deeply with Zod!

Questions Fréquemment Posées

La leçon « Développement de procédures de mutation » est-elle gratuite ?

Oui — le texte complet de « Développement de procédures de mutation » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours tRPC End-to-End Type Safe APIs, passe à CoddyKit PRO. Le cours tRPC End-to-End Type Safe APIs comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Développement de procédures de mutation » ?

Créez des procédures pour les opérations de création, de mise à jour et de suppression de données avec les procédures de mutation tRPC. Tu pratiques tRPC End-to-End Type Safe APIs avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer tRPC End-to-End Type Safe APIs ?

Aucune expérience préalable n'est requise. tRPC End-to-End Type Safe APIs sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Développement de procédures de mutation » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon tRPC End-to-End Type Safe APIs ?

Oui. Chaque leçon tRPC End-to-End Type Safe APIs inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Structurer une application avec les routeurs tRPC
  2. Implémentation de procédures de requête
  3. Développement de procédures de mutation
  4. Fusion et imbrication de routeurs
← Retour à tRPC End-to-End Type Safe APIs