JSPM

  • Created
  • Published
  • Downloads 5045
  • Score
    100M100P100Q135360F
  • License MIT

Send temporary data to the next request, usually from endpoints. Works with both SSR and client, and with redirects.

Package Exports

  • sveltekit-flash-message/client
  • sveltekit-flash-message/server

Readme

sveltekit-flash-message ⚡

This is a Sveltekit library that passes temporary data to the next request, usually from endpoints. It's useful when you want a "success" message displayed after a POST, which is not always displayed at the form, rather as a message on the page that the request was redirected to (since we are making well-behaved web apps that Redirects after Post).

This is known as a flash message, and it's especially well known in PHP apps, since it's easy to add this functionality with PHP's built-in session handling. With Sveltekit it's a bit harder, but this library was made to alleviate that.

Installation

pnpm i -D sveltekit-flash-message

Configuration

As usual, there are a few hoops to jump through:

1. [Typescript only] Add the flash message to app.d.ts

In src/app.d.ts you should add the type for the flash message to App.Session and App.Locals as an optional property called flash. It can be as simple as a string, or something more advanced. It has to be serializable though, so only JSON-friendly data structures. Here's an example:

src/app.d.ts

type FlashMessage = {type: 'success' | 'error', message: string}

declare namespace App {
  interface Locals {
    flash?: Session['flash']
  }

  interface Session {
    flash?: FlashMessage
  }
}

2. Implement hooks

If you're not using any SvelteKit hooks, this is a simple step. Create a src/hooks.ts file with the following content:

src/hooks.ts

export { handle, getSession } from 'sveltekit-flash-message/server'

If you've implemented a handle hook already, you can use sequence with the handleFlashMessage function instead:

src/hooks.ts

import { sequence } from '@sveltejs/kit/hooks'
import { handleFlashMessage } from 'sveltekit-flash-message/server'

const yourHandle : Handle = async ({ event, resolve }) => {
  // ...
}

export const handle = sequence(handleFlashMessage(), yourHandle)

If you've implemented getSession as well, just add the flash property to your own code:

src/hooks.ts

export const getSession = (event : RequestEvent) => {
  return {
    // ... other session variables here ...
    flash?: event.locals.flash
  }
}

3. Add lifecycle methods

After adding the hooks, the library is pretty much ready to use for SSR, but we want it to work client-side as well! To do this, you must add some lifecycle functions in a top-level component, most likely __layout.svelte:

src/routes/__layout.svelte

<script lang="ts">
  import { session } from '$app/stores';
  import { updateFlashMessage } from 'sveltekit-flash-message/client'
  import { onMount, beforeUpdate } from 'svelte';

  onMount(() => updateFlashMessage(session))
  beforeUpdate(() => updateFlashMessage(session))
</script>

This should take care of updates passed on from the endpoints, which is the next step to add:

4. Start using the library

Server-side: Update endpoints

To set the actual flash message, you'll import the flashMessage function in your endpoints, and use it on a RequestHandlerOutput (the structure you return from an endpoint). Here's an example from the Todo app, if your flash message is a string:

import { flashMessage } from 'sveltekit-flash-message/server'

export const POST : RequestHandler = async ({ request, locals }) => {
  const form = await request.formData();

  await api('POST', `todos/${locals.userid}`, {
    text: form.get('text')
  });

  const redirect = {
    status: 303,
    headers: {
      location: '/todos'
    }
  }

  // <App.Session['flash']> is optional, but helps with type-safety.
  return flashMessage<App.Session['flash']>("That's the entrepreneur spirit!", redirect)
}

Note: You should not add flash messages to GET requests! It causes caching and SSR problems, and goes against the idea of getting a message after an action is taken. The exception is if the GET request redirects, then it's useful as an explanation why the redirect happened.

Client-side: Update session directly

If you want to update the flash message on the client, just assign a new value to $session.flash.

5. Finally, display the flash message!

This is the simplest step of them all, just import session and use $session.flash like any other store:

YourComponent.svelte

<script lang="ts">
  import { session } from '$app/stores';
</script>

{#if $session.flash}
  <p><b>{$session.flash}</b></p>
{/if}

So much work, for so little?

It may seem so, but this library works for any kind of request, both SSR and client, which is trickier than it seems (and maybe trickier than what it should be...?)

Bonus: Removing flash message when navigating

This little snippet can be useful if you'd like to have the flash message removed when the user navigates to another route.

YourNavComponent.svelte

import { beforeNavigate } from '$app/navigation';
import { session } from '$app/stores';

beforeNavigate(nav => {
  if(nav.from.href != nav.to?.href && $session.flash) {
    $session.flash = undefined
  }
})

Finally, an important warning

Since the flash message is transferred in a cookie, it can be easily tampered with, so don't trust its content. Treat it like you do with any user data - hanging from a ten-foot pole over a fiery pit. 🔥

Enjoy the library, and please open a github issue if you have suggestions or feedback in general!