Skip to content

Commit bd82819

Browse files
dummdidummbenmccannghostdevvSymphonySimperteemingc
authored
docs: more Svelte 5 conversion (#12871)
--------- Co-authored-by: Ben McCann <[email protected]> Co-authored-by: Willow (GHOST) <[email protected]> Co-authored-by: Sri Senthil Balaji J <[email protected]> Co-authored-by: Tee Ming <[email protected]>
1 parent 4cdbf76 commit bd82819

File tree

11 files changed

+104
-77
lines changed

11 files changed

+104
-77
lines changed

documentation/docs/20-core-concepts/10-routing.md

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,22 @@ A `+page.svelte` component defines a page of your app. By default, pages are ren
3737
<a href="/">Home</a>
3838
```
3939

40+
Pages can receive data from `load` functions via the `data` prop.
41+
4042
```svelte
4143
<!--- file: src/routes/blog/[slug]/+page.svelte --->
4244
<script>
43-
/** @type {import('./$types').PageData} */
44-
export let data;
45+
/** @type {{ data: import('./$types').PageData }} */
46+
let { data } = $props();
4547
</script>
4648
4749
<h1>{data.title}</h1>
4850
<div>{@html data.content}</div>
4951
```
5052

53+
> [!LEGACY] In Svelte 4
54+
> In Svelte 4, you'd use `export let data` instead
55+
5156
> [!NOTE] Note that SvelteKit uses `<a>` elements to navigate between routes, rather than a framework-specific `<Link>` component.
5257
5358
### +page.js
@@ -153,21 +158,29 @@ But in many apps, there are elements that should be visible on _every_ page, suc
153158

154159
To create a layout that applies to every page, make a file called `src/routes/+layout.svelte`. The default layout (the one that SvelteKit uses if you don't bring your own) looks like this...
155160

156-
```html
157-
<slot></slot>
161+
```svelte
162+
<script>
163+
let { children } = $props();
164+
</script>
165+
166+
{@render children()}
158167
```
159168

160-
...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `<slot>` for the page content. For example, let's add a nav bar:
169+
...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `@render` tag for the page content. For example, let's add a nav bar:
170+
171+
```svelte
172+
<!---- file: src/routes/+layout.svelte --->
173+
<script>
174+
let { children } = $props();
175+
</script>
161176
162-
```html
163-
/// file: src/routes/+layout.svelte
164177
<nav>
165178
<a href="/">Home</a>
166179
<a href="/about">About</a>
167180
<a href="/settings">Settings</a>
168181
</nav>
169182
170-
<slot></slot>
183+
{@render children()}
171184
```
172185

173186
If we create pages for `/`, `/about` and `/settings`...
@@ -196,8 +209,8 @@ We can create a layout that only applies to pages below `/settings` (while inher
196209
```svelte
197210
<!--- file: src/routes/settings/+layout.svelte --->
198211
<script>
199-
/** @type {import('./$types').LayoutData} */
200-
export let data;
212+
/** @type {{ data: import('./$types').LayoutData, children: import('svelte').Snippet }} */
213+
let { data, children } = $props();
201214
</script>
202215
203216
<h1>Settings</h1>
@@ -208,7 +221,7 @@ We can create a layout that only applies to pages below `/settings` (while inher
208221
{/each}
209222
</div>
210223
211-
<slot></slot>
224+
{@render children()}
212225
```
213226

214227
You can see how `data` is populated by looking at the `+layout.js` example in the next section just below.
@@ -239,8 +252,8 @@ Data returned from a layout's `load` function is also available to all its child
239252
```svelte
240253
<!--- file: src/routes/settings/profile/+page.svelte --->
241254
<script>
242-
/** @type {import('./$types').PageData} */
243-
export let data;
255+
/** @type {{ data: import('./$types').PageData }} */
256+
let { data } = $props();
244257
245258
console.log(data.sections); // [{ slug: 'profile', title: 'Profile' }, ...]
246259
</script>
@@ -370,13 +383,13 @@ export async function fallback({ request }) {
370383
371384
Throughout the examples above, we've been importing types from a `$types.d.ts` file. This is a file SvelteKit creates for you in a hidden directory if you're using TypeScript (or JavaScript with JSDoc type annotations) to give you type safety when working with your root files.
372385
373-
For example, annotating `export let data` with `PageData` (or `LayoutData`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`:
386+
For example, annotating `let { data } = $props()` with `PageData` (or `LayoutData`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`:
374387
375388
```svelte
376389
<!--- file: src/routes/blog/[slug]/+page.svelte --->
377390
<script>
378-
/** @type {import('./$types').PageData} */
379-
export let data;
391+
/** @type {{ data: import('./$types').PageData }} */
392+
let { data } = $props();
380393
</script>
381394
```
382395

documentation/docs/20-core-concepts/20-load.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ export function load({ params }) {
2424
```svelte
2525
<!--- file: src/routes/blog/[slug]/+page.svelte --->
2626
<script>
27-
/** @type {import('./$types').PageData} */
28-
export let data;
27+
/** @type {{ data: import('./$types').PageData }} */
28+
let { data } = $props();
2929
</script>
3030
3131
<h1>{data.post.title}</h1>
3232
<div>{@html data.post.content}</div>
3333
```
3434

35+
> [!LEGACY] In Svelte 4
36+
> In Svelte 4, you'd use `export let data` instead
37+
3538
Thanks to the generated `$types` module, we get full type safety.
3639

3740
A `load` function in a `+page.js` file runs both on the server and in the browser (unless combined with `export const ssr = false`, in which case it will [only run in the browser](page-options#ssr)). If your `load` function should _always_ run on the server (because it uses private environment variables, for example, or accesses a database) then it would go in a `+page.server.js` instead.
@@ -85,13 +88,13 @@ export async function load() {
8588
```svelte
8689
<!--- file: src/routes/blog/[slug]/+layout.svelte --->
8790
<script>
88-
/** @type {import('./$types').LayoutData} */
89-
export let data;
91+
/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
92+
let { data, children } = $props();
9093
</script>
9194
9295
<main>
93-
<!-- +page.svelte is rendered in this <slot> -->
94-
<slot />
96+
<!-- +page.svelte is `@render`ed here -->
97+
{@render children()}
9598
</main>
9699
97100
<aside>
@@ -115,13 +118,13 @@ Data returned from layout `load` functions is available to child `+layout.svelte
115118
<script>
116119
+++import { page } from '$app/stores';+++
117120
118-
/** @type {import('./$types').PageData} */
119-
export let data;
121+
/** @type {{ data: import('./$types').PageData }} */
122+
let { data } = $props();
120123
121124
+++ // we can access `data.posts` because it's returned from
122125
// the parent layout `load` function
123126
let index = $derived(data.posts.findIndex(post => post.slug === $page.params.slug));
124-
let next = $derived(data.posts[index - 1];)+++
127+
let next = $derived(data.posts[index + 1]);+++
125128
</script>
126129
127130
<h1>{data.post.title}</h1>
@@ -365,8 +368,8 @@ export async function load({ parent }) {
365368
```svelte
366369
<!--- file: src/routes/abc/+page.svelte --->
367370
<script>
368-
/** @type {import('./$types').PageData} */
369-
export let data;
371+
/** @type {{ data: import('./$types').PageData }} */
372+
let { data } = $props();
370373
</script>
371374
372375
<!-- renders `1 + 2 = 3` -->
@@ -504,8 +507,8 @@ This is useful for creating skeleton loading states, for example:
504507
```svelte
505508
<!--- file: src/routes/blog/[slug]/+page.svelte --->
506509
<script>
507-
/** @type {import('./$types').PageData} */
508-
export let data;
510+
/** @type {{ data: import('./$types').PageData }} */
511+
let { data } = $props();
509512
</script>
510513
511514
<h1>{data.post.title}</h1>
@@ -645,8 +648,8 @@ export async function load({ fetch, depends }) {
645648
<script>
646649
import { invalidate, invalidateAll } from '$app/navigation';
647650
648-
/** @type {import('./$types').PageData} */
649-
export let data;
651+
/** @type {{ data: import('./$types').PageData }} */
652+
let { data } = $props();
650653
651654
function rerunLoadFunction() {
652655
// any of these will cause the `load` function to rerun

documentation/docs/20-core-concepts/30-form-actions.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,8 @@ export const actions = {
140140
```svelte
141141
<!--- file: src/routes/login/+page.svelte --->
142142
<script>
143-
/** @type {import('./$types').PageData} */
144-
export let data;
145-
146-
/** @type {import('./$types').ActionData} */
147-
export let form;
143+
/** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
144+
let { data, form } = $props();
148145
</script>
149146

150147
{#if form?.success}
@@ -154,6 +151,9 @@ export const actions = {
154151
{/if}
155152
```
156153
154+
> [!LEGACY] In Svelte 4
155+
> In Svelte 4, you'd use `export let data` and `export let form` instead to declare properties
156+
157157
### Validation errors
158158
159159
If the request couldn't be processed because of invalid data, you can return validation errors — along with the previously submitted form values — back to the user so that they can try again. The `fail` function lets you return an HTTP status code (typically 400 or 422, in the case of validation errors) along with the data. The status code is available through `$page.status` and the data through `form`:
@@ -339,8 +339,8 @@ The easiest way to progressively enhance a form is to add the `use:enhance` acti
339339
<script>
340340
+++import { enhance } from '$app/forms';+++
341341

342-
/** @type {import('./$types').ActionData} */
343-
export let form;
342+
/** @type {{ form: import('./$types').ActionData }} */
343+
let { form } = $props();
344344
</script>
345345

346346
<form method="POST" +++use:enhance+++>
@@ -390,8 +390,8 @@ If you return a callback, you may need to reproduce part of the default `use:enh
390390
<script>
391391
import { enhance, +++applyAction+++ } from '$app/forms';
392392

393-
/** @type {import('./$types').ActionData} */
394-
export let form;
393+
/** @type {{ form: import('./$types').ActionData }} */
394+
let { form } = $props();
395395
</script>
396396

397397
<form
@@ -427,11 +427,8 @@ We can also implement progressive enhancement ourselves, without `use:enhance`,
427427
import { invalidateAll, goto } from '$app/navigation';
428428
import { applyAction, deserialize } from '$app/forms';
429429

430-
/** @type {import('./$types').ActionData} */
431-
export let form;
432-
433-
/** @type {any} */
434-
let error;
430+
/** @type {{ form: import('./$types').ActionData }} */
431+
let { form } = $props();
435432

436433
/** @param {{ currentTarget: EventTarget & HTMLFormElement}} event */
437434
async function handleSubmit(event) {

documentation/docs/20-core-concepts/50-state-management.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,14 @@ You might wonder how we're able to use `$page.data` and other [app stores]($app-
9090
import { setContext } from 'svelte';
9191
import { writable } from 'svelte/store';
9292
93-
/** @type {import('./$types').LayoutData} */
94-
export let data;
93+
/** @type {{ data: import('./$types').LayoutData }} */
94+
let { data } = $props();
9595
9696
// Create a store and update it when necessary...
97-
const user = writable();
98-
$: user.set(data.user);
97+
const user = writable(data.user);
98+
$effect.pre(() => {
99+
user.set(data.user);
100+
});
99101
100102
// ...and add it to the context for child components to access
101103
setContext('user', user);
@@ -125,8 +127,8 @@ When you navigate around your application, SvelteKit reuses existing layout and
125127
```svelte
126128
<!--- file: src/routes/blog/[slug]/+page.svelte --->
127129
<script>
128-
/** @type {import('./$types').PageData} */
129-
export let data;
130+
/** @type {{ data: import('./$types').PageData }} */
131+
let { data } = $props();
130132
131133
// THIS CODE IS BUGGY!
132134
const wordCount = data.content.split(' ').length;
@@ -148,8 +150,8 @@ Instead, we need to make the value [_reactive_](/tutorial/svelte/state):
148150
```svelte
149151
/// file: src/routes/blog/[slug]/+page.svelte
150152
<script>
151-
/** @type {import('./$types').PageData} */
152-
export let data;
153+
/** @type {{ data: import('./$types').PageData }} */
154+
let { data } = $props();
153155
154156
+++ let wordCount = $state(data.content.split(' ').length);
155157
let estimatedReadingTime = $derived(wordCount / 250);+++

documentation/docs/25-build-and-deploy/90-adapter-vercel.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ export function load() {
140140
```svelte
141141
<!--- file: +layout.svelte --->
142142
<script>
143-
/** @type {import('./$types').LayoutServerData} */
144-
export let data;
143+
/** @type {{ data: import('./$types').LayoutServerData }} */
144+
let { data } = $props();
145145
</script>
146146
147147
<p>This staging environment was deployed from {data.deploymentGitBranch}.</p>

documentation/docs/30-advanced/10-advanced-routing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ You can also put a `+page` directly inside a `(group)`, for example if `/` shoul
193193

194194
### Breaking out of layouts
195195

196-
The root layout applies to every page of your app — if omitted, it defaults to `<slot />`. If you want some pages to have a different layout hierarchy than the rest, then you can put your entire app inside one or more groups _except_ the routes that should not inherit the common layouts.
196+
The root layout applies to every page of your app — if omitted, it defaults to `{@render children()}`. If you want some pages to have a different layout hierarchy than the rest, then you can put your entire app inside one or more groups _except_ the routes that should not inherit the common layouts.
197197

198198
In the example above, the `/admin` route does not inherit either the `(app)` or `(marketing)` layouts.
199199

@@ -260,11 +260,11 @@ Not all use cases are suited for layout grouping, nor should you feel compelled
260260
<!--- file: src/routes/nested/route/[email protected] --->
261261
<script>
262262
import ReusableLayout from '$lib/ReusableLayout.svelte';
263-
export let data;
263+
let { data, children } = $props();
264264
</script>
265265
266266
<ReusableLayout {data}>
267-
<slot />
267+
{@render children()}
268268
</ReusableLayout>
269269
```
270270

documentation/docs/30-advanced/65-snapshots.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ To do this, export a `snapshot` object with `capture` and `restore` methods from
1111
```svelte
1212
<!--- file: +page.svelte --->
1313
<script>
14-
let comment = '';
14+
let comment = $state('');
1515
1616
/** @type {import('./$types').Snapshot<string>} */
1717
export const snapshot = {

documentation/docs/30-advanced/67-shallow-routing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ For this to work, you need to load the data that the `+page.svelte` expects. A c
5151
import Modal from './Modal.svelte';
5252
import PhotoPage from './[id]/+page.svelte';
5353
54-
export let data;
54+
let { data } = $props();
5555
</script>
5656
5757
{#each data.thumbnails as thumbnail}

documentation/docs/98-reference/26-$lib.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,18 @@
22
title: $lib
33
---
44

5-
TODO
5+
SvelteKit automatically makes files under `src/lib` available using the `$lib` import alias. You can change which directory this alias points to in your [config file](configuration#files).
6+
7+
```svelte
8+
<!--- file: src/lib/Component.svelte --->
9+
A reusable component
10+
```
11+
12+
```svelte
13+
<!--- file: src/routes/+page.svelte --->
14+
<script>
15+
import Component from '$lib/Component.svelte';
16+
</script>
17+
18+
<Component />
19+
```

0 commit comments

Comments
 (0)