Skip to content

Using page in $app/state with superforms #50

@benquan

Description

@benquan

I have the following code which is referencing page in $app/stores (in +layout.svelte)

SveltLab demo

It is currently working fine, but I want to move over to use $app/state, for what I understand in documentation, the change should be as simple as changing the source of the import. But when I do so I start getting strange errors.

If you change +layout.svelte
from

	import { page } from '$app/stores';

to

	import { page } from '$app/state';

The flash message will not show anymore and Console will give the error: Uncaught (in promise) Svelte error: lifecycle_outside_component `onDestroy(...)` can only be used during component initialisation

Same demo but with the error applied:

Sveltelab with Error

The orginal code is the follwing:
+layout.server.ts

import { loadFlash } from 'sveltekit-flash-message/server';

export const load = loadFlash(async (event) => {
    const data = { someOther: 'data' };
    return data;
});

+layout.svelte

<script lang="ts">
	import { getFlash } from 'sveltekit-flash-message';
	import { page } from '$app/stores';
	import '../app.css';

	let { children } = $props();

	const flash = getFlash(page);
</script>

{@render children()}

{#if $flash}
	{@const bg = $flash.type == 'success' ? '#3D9970' : '#FF4136'}
	<div style:background-color={bg} class="flash">{$flash.message}</div>
{/if}

+page.server.ts

import { message, superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
import { schema } from './schema.js';

export const load = async () => {
    return { form: await superValidate(zod(schema)) };
};

export const actions = {
    default: async ({ request }) => {
        const form = await superValidate(request, zod(schema));
        console.log(form);

        return message(form, { type: 'success', message: 'Form posted successfully!' });
    }
};

+page.svelte

<script lang="ts">
	import SuperDebug, { superForm } from 'sveltekit-superforms';
	import * as flashModule from 'sveltekit-flash-message/client';

	let { data } = $props();

	const { form, errors, constraints, enhance } = superForm(data.form, {
		flashMessage: {
			module: flashModule
		},
		syncFlashMessage: true
	});
</script>

<div class="container">
	<form method="POST" class="form" use:enhance>
		<label for="name" class="label">Name</label>
		<input type="text" name="name" bind:value={$form.name} class="input" {...$constraints.name} />
		{#if $errors.name}<span class="invalid">{$errors.name}</span>{/if}

		<label for="age" class="label">Age</label>
		<input type="number" name="age" bind:value={$form.age} class="input" {...$constraints.age} />
		{#if $errors.age}<span class="invalid">{$errors.age}</span>{/if}

		<div>
			<button class="submit-button"> Submit </button>
		</div>
	</form>
</div>

<SuperDebug data={$form} />

<style>
	.container {
		margin: 2rem auto;
		max-width: 28rem;
		background-color: white;
		padding: 1.5rem;
		border-radius: 0.5rem;
		box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
	}

	.label {
		display: block;
		margin-bottom: 0.5rem;
		font-weight: 500;
		color: #374151;
	}

	.input {
		width: 100%;
		margin-bottom: 1rem;
		padding: 0.5rem 0.75rem;
		border: 1px solid #d1d5db;
		border-radius: 0.375rem;
	}

	.input:focus {
		outline: none;
		border-color: #3b82f6;
		box-shadow: 0 0 0 2px #3b82f6;
	}

	.submit-button {
		width: 100%;
		background-color: #3b82f6;
		color: white;
		padding: 0.5rem 1rem;
		border-radius: 0.375rem;
		transition: background-color 0.2s;
	}

	.submit-button:hover {
		background-color: #2563eb;
	}

	.submit-button:focus {
		outline: none;
		box-shadow:
			0 0 0 2px #3b82f6,
			0 0 0 4px #fff;
	}

	.invalid {
		color: red;
	}
</style>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions