Skip to content

Commit

Permalink
Sync svelte docs (#1101)
Browse files Browse the repository at this point in the history
sync svelte docs

Co-authored-by: Rich-Harris <[email protected]>
  • Loading branch information
github-actions[bot] and Rich-Harris authored Jan 9, 2025
1 parent ab7481b commit 4c54849
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 50 deletions.
117 changes: 68 additions & 49 deletions apps/svelte.dev/content/docs/svelte/07-misc/07-v5-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,31 @@ When spreading props, local event handlers must go _after_ the spread, or they r

In Svelte 4, content can be passed to components using slots. Svelte 5 replaces them with snippets which are more powerful and flexible, and as such slots are deprecated in Svelte 5.

They continue to work, however, and you can mix and match snippets and slots in your components.
They continue to work, however, and you can pass snippets to a component that uses slots:

```svelte
<!--- file: Child.svelte --->
<slot />
<hr />
<slot name="foo" message="hello" />
```

```svelte
<!--- file: Parent.svelte --->
<script>
import Child from './Child.svelte';
</script>
<Child>
default child content
{#snippet foo({ message })}
message from child: {message}
{/snippet}
</Child>
```

(The reverse is not true — you cannot pass slotted content to a component that uses [`{@render ...}`](/docs/svelte/@render) tags.)

When using custom elements, you should still use `<slot />` like before. In a future version, when Svelte removes its internal version of slots, it will leave those slots as-is, i.e. output a regular DOM tag instead of transforming it.

Expand Down Expand Up @@ -598,28 +622,57 @@ export declare const MyComponent: Component<{

To declare that a component of a certain type is required:

```js
import { ComponentA, ComponentB } from 'component-library';
---import type { SvelteComponent } from 'svelte';---
+++import type { Component } from 'svelte';+++

---let C: typeof SvelteComponent<{ foo: string }> = $state(---
+++let C: Component<{ foo: string }> = $state(+++
Math.random() ? ComponentA : ComponentB
);
```
The two utility types `ComponentEvents` and `ComponentType` are also deprecated. `ComponentEvents` is obsolete because events are defined as callback props now, and `ComponentType` is obsolete because the new `Component` type is the component type already (i.e. `ComponentType<SvelteComponent<{ prop: string }>>` is equivalent to `Component<{ prop: string }>`).
### bind:this changes
Because components are no longer classes, using `bind:this` no longer returns a class instance with `$set`, `$on` and `$destroy` methods on it. It only returns the instance exports (`export function/const`) and, if you're using the `accessors` option, a getter/setter-pair for each property.

## `<svelte:component>` is no longer necessary

In Svelte 4, components are _static_ — if you render `<Thing>`, and the value of `Thing` changes, [nothing happens](/playground/7f1fa24f0ab44c1089dcbb03568f8dfa?version=4.2.18). To make it dynamic you had to use `<svelte:component>`.

This is no longer true in Svelte 5:

```svelte
<script lang="ts">
import type { ---SvelteComponent--- +++Component+++ } from 'svelte';
import {
ComponentA,
ComponentB
} from 'component-library';
<script>
import A from './A.svelte';
import B from './B.svelte';

---let component: typeof SvelteComponent<{ foo: string }>---
+++let component: Component<{ foo: string }>+++ = $state(
Math.random() ? ComponentA : ComponentB
);
let Thing = $state();
</script>

<svelte:component this={component} foo="bar" />
<select bind:value={Thing}>
<option value={A}>A</option>
<option value={B}>B</option>
</select>

<!-- these are equivalent -->
<Thing />
<svelte:component this={Thing} />
```
While migrating, keep in mind that your component's name should be capitalized (`Thing`) to distinguish it from elements, unless using dot notation.
The two utility types `ComponentEvents` and `ComponentType` are also deprecated. `ComponentEvents` is obsolete because events are defined as callback props now, and `ComponentType` is obsolete because the new `Component` type is the component type already (e.g. `ComponentType<SvelteComponent<{ prop: string }>>` == `Component<{ prop: string }>`).
### Dot notation indicates a component
### bind:this changes
In Svelte 4, `<foo.bar>` would create an element with a tag name of `"foo.bar"`. In Svelte 5, `foo.bar` is treated as a component instead. This is particularly useful inside `each` blocks:
Because components are no longer classes, using `bind:this` no longer returns a class instance with `$set`, `$on` and `$destroy` methods on it. It only returns the instance exports (`export function/const`) and, if you're using the `accessors` option, a getter/setter-pair for each property.
```svelte
{#each items as item}
<item.component {...item.props} />
{/each}
```
## Whitespace handling changed
Expand Down Expand Up @@ -654,16 +707,6 @@ The `legacy` compiler option, which generated bulkier but IE-friendly code, no l
Content inside component tags becomes a snippet prop called `children`. You cannot have a separate prop by that name.
## Dot notation indicates a component

In Svelte 4, `<foo.bar>` would create an element with a tag name of `"foo.bar"`. In Svelte 5, `foo.bar` is treated as a component instead. This is particularly useful inside `each` blocks:

```svelte
{#each items as item}
<item.component {...item.props} />
{/each}
```

## Breaking changes in runes mode
Some breaking changes only apply once your component is in runes mode.
Expand Down Expand Up @@ -701,30 +744,6 @@ In Svelte 4, doing the following triggered reactivity:
This is because the Svelte compiler treated the assignment to `foo.value` as an instruction to update anything that referenced `foo`. In Svelte 5, reactivity is determined at runtime rather than compile time, so you should define `value` as a reactive `$state` field on the `Foo` class. Wrapping `new Foo()` with `$state(...)` will have no effect — only vanilla objects and arrays are made deeply reactive.
### `<svelte:component>` is no longer necessary

In Svelte 4, components are _static_ — if you render `<Thing>`, and the value of `Thing` changes, [nothing happens](/playground/7f1fa24f0ab44c1089dcbb03568f8dfa?version=4.2.18). To make it dynamic you must use `<svelte:component>`.

This is no longer true in Svelte 5:

```svelte
<script>
import A from './A.svelte';
import B from './B.svelte';
let Thing = $state();
</script>
<select bind:value={Thing}>
<option value={A}>A</option>
<option value={B}>B</option>
</select>
<!-- these are equivalent -->
<Thing />
<svelte:component this={Thing} />
```

### Touch and wheel events are passive
When using `onwheel`, `onmousewheel`, `ontouchstart` and `ontouchmove` event attributes, the handlers are [passive](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners) to align with browser defaults. This greatly improves responsiveness by allowing the browser to scroll the document immediately, rather than waiting to see if the event handler calls `event.preventDefault()`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ NOTE: do not edit this file, it is generated in apps/svelte.dev/scripts/sync-doc
title: <svelte:component>
---

In runes mode, `<MyComponent>` will re-render if the value of `MyComponent` changes. See the [Svelte 5 migration guide](/docs/svelte/v5-migration-guide#Breaking-changes-in-runes-mode-svelte:component-is-no-longer-necessary) for an example.
In runes mode, `<MyComponent>` will re-render if the value of `MyComponent` changes. See the [Svelte 5 migration guide](/docs/svelte/v5-migration-guide#svelte:component-is-no-longer-necessary) for an example.

In legacy mode, it won't — we must use `<svelte:component>`, which destroys and recreates the component instance when the value of its `this` expression changes:

Expand Down

0 comments on commit 4c54849

Please sign in to comment.