Bird
Raised Fist0
Svelteframework~5 mins

Hooks (handle, handleError, handleFetch) in Svelte

Choose your learning style10 modes available
Introduction

Hooks let you run code at key moments in your app's life. They help you manage requests, errors, and responses easily.

You want to add a loading spinner or log every request your app makes.
You need to catch and show friendly messages when something goes wrong.
You want to modify data coming from the server before your app uses it.
You want to add headers or tokens to every fetch request automatically.
Syntax
Svelte
export const handle = async ({ event, resolve }) => {
  // your code here
  const response = await resolve(event);
  return response;
};

export const handleError = ({ error, event }) => {
  // your code here
};

export const handleFetch = async ({ request, fetch }) => {
  // your code here
  const response = await fetch(request);
  return response;
};

handle runs on every request and response cycle.

handleError runs when an error happens during a request.

Examples
This logs the URL of every request your app receives.
Svelte
export const handle = async ({ event, resolve }) => {
  console.log('Request URL:', event.url.href);
  const response = await resolve(event);
  return response;
};
This logs error messages to the console when something goes wrong.
Svelte
export const handleError = ({ error, event }) => {
  console.error('Error caught:', error.message);
};
This adds a custom header to every fetch request your app makes.
Svelte
export const handleFetch = async ({ request, fetch }) => {
  const modifiedRequest = new Request(request, {
    headers: { ...Object.fromEntries(request.headers), 'X-Custom-Header': 'MyValue' }
  });
  const response = await fetch(modifiedRequest);
  return response;
};
Sample Program

This example shows all three hooks working together. It logs requests, fetches, and errors with clear messages.

Svelte
export const handle = async ({ event, resolve }) => {
  console.log(`Handling request for: ${event.url.pathname}`);
  const response = await resolve(event);
  return response;
};

export const handleError = ({ error, event }) => {
  console.error(`Error on ${event.url.pathname}: ${error.message}`);
};

export const handleFetch = async ({ request, fetch }) => {
  console.log(`Fetching: ${request.url}`);
  const response = await fetch(request);
  return response;
};
OutputSuccess
Important Notes

Hooks run on the server side in SvelteKit, so you can safely handle secrets here.

Always return the response from handle and handleFetch to keep the app working.

Use handleError to log or show user-friendly error messages.

Summary

Hooks let you run code during requests, errors, and fetches.

handle manages requests and responses.

handleError catches and handles errors.

handleFetch lets you change fetch requests and responses.

Practice

(1/5)
1. What is the main purpose of the handle hook in SvelteKit?
easy
A. To catch and handle errors during server-side rendering
B. To define client-side event handlers for UI elements
C. To intercept and modify fetch requests made by the app
D. To manage and modify incoming requests and outgoing responses

Solution

  1. Step 1: Understand the role of handle hook

    The handle hook runs on every request and can modify the request or response.
  2. Step 2: Compare with other hooks

    handleError is for errors, handleFetch is for fetch interception, so they don't manage requests/responses directly.
  3. Final Answer:

    To manage and modify incoming requests and outgoing responses -> Option D
  4. Quick Check:

    handle = manage requests/responses [OK]
Hint: Remember: handle = request/response management [OK]
Common Mistakes:
  • Confusing handle with handleError
  • Thinking handleFetch manages requests directly
  • Assuming handle is for client-side events
2. Which of the following is the correct syntax to define a handleError hook in hooks.server.js?
easy
A. export function handleError({ request, response }) { return response; }
B. export async function handleError(event) { console.error(event.error); }
C. export function handleError({ error, event }) { return { message: error.message }; }
D. export function handleError({ fetch, event }) { return fetch(event); }

Solution

  1. Step 1: Recall handleError parameters

    The handleError hook receives an object with error and event.
  2. Step 2: Check syntax correctness

    export function handleError({ error, event }) { return { message: error.message }; } correctly destructures { error, event } and returns an object with a message.
  3. Final Answer:

    export function handleError({ error, event }) { return { message: error.message }; } -> Option C
  4. Quick Check:

    handleError({ error, event }) correct syntax [OK]
Hint: handleError gets { error, event } object [OK]
Common Mistakes:
  • Using wrong parameters like request or fetch
  • Not destructuring the error object
  • Returning response instead of error info
3. Given this handleFetch hook, what will be logged when the app fetches /api/data?
export async function handleFetch({ request, fetch }) {
  console.log('Fetching:', request.url);
  const response = await fetch(request);
  return response;
}
medium
A. Fetching: http://localhost/api/data
B. Fetching: /api/data
C. Fetching: undefined
D. No output logged

Solution

  1. Step 1: Understand handleFetch parameters

    The request object has a full URL in its url property.
  2. Step 2: Analyze the console.log statement

    The code logs 'Fetching:' plus the full request.url, which includes the origin like 'http://localhost/api/data'.
  3. Final Answer:

    Fetching: http://localhost/api/data -> Option A
  4. Quick Check:

    request.url logs full URL [OK]
Hint: request.url in handleFetch is full URL [OK]
Common Mistakes:
  • Expecting only path instead of full URL
  • Thinking request.url is undefined
  • Assuming no console output
4. Identify the error in this handle hook code snippet:
export async function handle({ event, resolve }) {
  const response = await resolve(event);
  response.headers.set('X-Custom', 'value');
  return response;
}
medium
A. Cannot modify headers on the response object directly; it is immutable
B. Missing await before resolve(event)
C. Incorrect parameter names; should be { request, resolve }
D. handle hook must be synchronous, not async

Solution

  1. Step 1: Check response header modification

    The response object is immutable; headers cannot be set directly on it.
  2. Step 2: Confirm other parts are correct

    Await is used correctly, parameter names are valid, and handle can be async.
  3. Final Answer:

    Cannot modify headers on the response object directly; it is immutable -> Option A
  4. Quick Check:

    Response headers are immutable [OK]
Hint: Response headers are immutable; clone before modifying [OK]
Common Mistakes:
  • Trying to set headers directly on response
  • Confusing parameter names
  • Thinking handle must be synchronous
5. You want to add a custom header X-User with the username from event.locals.user to every fetch request made by your app. Which handleFetch hook implementation correctly achieves this?
hard
A. export async function handleFetch({ request, fetch }) { request.headers.set('X-User', event.locals.user); return fetch(request); }
B. export async function handleFetch({ request, fetch, event }) { const modifiedRequest = new Request(request, { headers: { ...Object.fromEntries(request.headers), 'X-User': event.locals.user } }); return fetch(modifiedRequest); }
C. export async function handleFetch({ request, fetch, event }) { request.headers.append('X-User', event.locals.user); return fetch(request); }
D. export async function handleFetch({ request, fetch, event }) { const headers = new Headers(request.headers); headers.set('X-User', event.locals.user); const modifiedRequest = new Request(request.url, { method: request.method, headers }); return fetch(modifiedRequest); }

Solution

  1. Step 1: Understand immutability of request headers

    Request headers are immutable; to modify them, create a new Request with new headers while preserving other properties like body.
  2. Step 2: Analyze the correct implementation

    The code that uses new Request(request, { headers: { ...Object.fromEntries(request.headers), 'X-User': event.locals.user } }) clones the original request fully (including body, method, etc.) and overrides the headers correctly.
  3. Step 3: Identify errors in other options

    Directly modifying request.headers with set or append fails because headers are immutable. Creating a new Request with only url, method, and headers omits the body and other request properties.
  4. Final Answer:

    export async function handleFetch({ request, fetch, event }) { const modifiedRequest = new Request(request, { headers: { ...Object.fromEntries(request.headers), 'X-User': event.locals.user } }); return fetch(modifiedRequest); } -> Option B
  5. Quick Check:

    new Request(request, { headers: ... }) clones fully [OK]
Hint: Clone request with new Request(request, { headers: updated }) [OK]
Common Mistakes:
  • Modifying headers directly on original request
  • Not cloning request before changing headers
  • Omitting request body when recreating Request
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard