Updates

These posts are aggregated from Svelte GitHub Repository.

  • Svelte Philosophy

    This is an attempt to articulate the Svelte philosophy — our bedrock principles, that guide our design decisions.
  • Is there an option for lazy async derived?

    Essentially the question is if there is an option to make an async derived resolve immediately and update later with the value of the resolved promise.

    Currently I use this:

    <script>
      // some promise for example from load function
      let promise = $state(new Promise(() => {}));
      
      // initially undefined
      let data = $state();
      
      // update the data when the promise resolves and also when the promise changes
      $effect(() => {
        promise.then((newData) => (data = newData));
      });
    </script>
    

    Because when I try to use async derived it blocks until the promise resolves and i don't want to wait to render the UI until the data is loaded:

    <script>
      // some promise for example from load function
      let promise = $state(new Promise(() => {}));
      
      // blocks forever in this case because the promise never resolves
      let data = $derived(await promise);
    </script>
    

    Is there a way to give derived a default value sort of like this?

    <script>
      // some promise for example from load function
      let promise = $state(new Promise(() => {}));
      
      // resolves instantly to undefined and gets updated later when the actual promise resolves
      let data = $derived(await promise, undefined);
    </script>
    

    There is also this solution from shadcn svelte extra but it is still not as clean as builtin way

  • Passing Snippet to grandchildren

    I have template module (shown below) which should be unaware of any view being fed into it: Render1, Render2, etc. The view in this case is the grandchildView which needs to be passed down to GrandChildTemplate component. I utilise context but wonder if there is a better way to do it without context or passing props all the way down?

    I don't mind if it is Svelte4 or Svelte5 solution.

    // Render1.svelte
    <ParentTemplate>{#snippet grandchildView()}<a>grandchild render1</a>{/snippet}</ParentTemplate>
    
    // Render2.svelte
    <ParentTemplate>{#snippet grandchildView()}<a>grandchild render2</a>{/snippet}</ParentTemplate>
    
    // Render3.svelte
    <ParentTemplate>{#snippet grandchildView()}<a>grandchild render3</a>{/snippet}</ParentTemplate>
    
    
    // ParentTemplate.svelte
    const {grandchildView} = $props();
    setContext('grandchildView', grandchildView);
    {#each children as child}<ChildTemplate {child} />{/each}
    
    // ChildTemplate.svelte
    {#each grandChildren as grandChild}<GrandChildTemplate {grandChild} />{/each}
    
    // GrandChildTemplate.svelte
    const grandchildView = getContext('grandchildView');
    {@render grandchildView()}
    
  • How to correctly type a custom element event bubbling on the imported component?

    I tried a few things but each doesn't seem to type correctly.

    // Melt types
    export type EventHandler<T extends Event = Event> = (event: T) => void;
    export type MeltEvent<E extends Event> = CustomEvent<{
        originalEvent: E;
    }>;
    export type MeltEventHandler<E extends Event> = EventHandler<Expand<Omit<MeltEvent<E>, 'initCustomEvent'>>>;
    
    // Svelte DOM enhancement
    declare module "svelte/elements" {
        // works for the button element
        export interface DOMAttributes {
            "on:m-click"?: MeltEventHandler<MouseEvent> | undefined | null;
        }
    
        // this work for the button element as well
        export interface HTMLButtonAttributes {
            "on:m-click": MeltEventHandler<MouseEvent> | undefined | null;
        }
    }
    
    // button.svelte
    // this will correctly be typed as defined above
    ...
    <button on:m-click on:m-click={(e) => void}>button</button>
    ...
    
    // app.svelte
    // On the component the type will be every possible Event (m-click: Event | MouseEvent | UIEvent | ClipboardEvent | CompositionEvent | FocusEvent | InputEvent | ... 11 more ... | SecurityPolicyViolationEvent)
    )
    ...
    <Button on:m-click={(e) => void}>
    
    // Even if I declare the handler within the `script` tag with the `ComponentEvents` type it still defaults to a generic handler.
    <script lang="ts">
    // ...
    const handler = async (e: ComponentEvents<Button>["m-click"]) => void);
    // ...
    </script>
    

    I'm guessing that Svelte is defaulting the type of any on:${string} as a generic event handler. Is there a way to narrow the type such as when I use on:m-click on the Button component, it correctly assesses the type as it is in the declare module?

  • Support for Intl.supportedValuesOf?

    Perhaps I'm looking in the wrong place, but in VSCode (using the Svelte extension - v108.1.0) I'm getting a warning when I use Intl.supportedValuesOf stating that supportedValuesOf it is not part of Intl.

    This feature is fully supported by all major browsers.

    I made sure to set VSCode's Typescript support to ESNext, but that doesn't seem to make any difference. A similar issue was reported to VSCode's team, but they said it was the responsibility of the extension owner.

    I so I guess my question is, has anyone run into this issue and is the right place to fix this at the Svelte VSCode extension? Any tips on how to make the warning go away?

  • Async updates in setter of bind:value

    Hi! I have a question about the idiomatic way to handle async state updates with bind:.

    Let's say I have a simple wrapper around <input type="checkbox">:

    <script lang="ts">
        let { checked = $bindable() } = $props();
    </script>
    
    <input
        type="checkbox"
        bind:checked
    />
    

    Usage with local state works perfectly fine:

    let isChecked = $state(false);
    
    <Checkbox bind:checked={isChecked} />
    

    But sometimes the value comes from some external reactive source where updating it requires an async request to the backend.

    One possible approach is using function bindings:

    <Checkbox
        bind:checked={() => some.reactive.field, (value) => {
             requestToUpdateMyField(value);
        }}
    />
    

    However, I'm not sure whether performing side effects / async requests inside a bind setter is considered idiomatic in Svelte.

    Another option would be treating the component as controlled and handling updates separately:

    <Checkbox
        checked={some.reactive.field}
        onChange={(value) => {
            requestToUpdateMyField(value);
        }}
    />
    

    But in that case, what’s the point of making checked bindable?

    Also, is it considered normal for a component to support both approaches simultaneously?

    For example:

    • use bind: for simple/local state
    • use onChange for async/server-backed updates

    Or is it better to encourage only a single pattern consistently across the component API?

    Would appreciate any guidance or examples from Svelte community.

  • Get svelte version from svelte/compiler adds a large amount of code to the build...

    import { VERSION as svelteVersion } from "svelte/compiler";
    

    I've seen this issue before but can't find it anymore. Doing this import adds a lot of code to build, around 600kB I'm not sure why and all I want is the version of the compiler...

    Perhaps importing from 'svelte/compiler' is not the way to go about it but then the docs should be updated?

    Anyone else seen this?

  • Missing Conditional Rendering

    Hi, the template syntax: https://svelte.dev/docs/svelte/if is great. But imagine if there are many lists:

    {#if maybe}
        <ul>
            {#each { length: 999 }, i}
                <li>{i}</li>
            {/each}
        </>
    {/if}
    

    This might not efficient to the DOM, especially if the condition keep being toggle like a sidebar.

    Is there a feature like Vue: https://vuejs.org/guide/essentials/conditional.html#v-show where it only use CSS to hide it?

    I know I can use $state() and use class like the doc did: https://svelte.dev/docs/svelte/class But it's just not convenient. Is it possible to do something like:

    {#show maybe}
        <ul>
            {#each { length: 999 }, i}
                <li>{i}</li>
            {/each}
        </>
    {/if}
    
  • How can a beginner start building real-world frontend projects?

    Hi everyone,

    I am currently learning frontend development (HTML, CSS, JavaScript) and want to start building real-world projects.

    What are the best beginner-friendly projects and how can I improve my problem-solving skills while learning?

    Any guidance would be appreciated.

    Prinjal Kumari, Frontend Beginner, iCreativez

  • Derived stateful classes

    Is there an idiomatic way to do this? basically i have state, then I have some derived state but it's not pure - it's stateful too. here's a basic example

    
    class Counter {
        counter = $state(0);
    }
    
    class CounterWithAdded {
        counter = $state(0);
    
        sum;
        constructor(props: { add: number }) {
            this.sum = $derived(this.counter + props.add);
        }
    }
    
    const a = new Counter();
    
    // no, this will reset internal counter every time
    const c1 = $derived(new CounterWithAdded({ add: a.counter }));
    
    // recommended approach but wieldy when you have several options like that
    const c2 = new CounterWithAdded({
        get add() {
            return a.counter;
        },
    });
    
    // works and less verbose when a lot of properties probably but feels icky
    class AddProps {
        add = $derived(a.counter);
    }
    const c3 = new CounterWithAdded(new AddProps());
    

    as for the real use case - we're a bank and we have a lot of functions built around svelte 4 stores where a function sets up a bunch of state, and then reused by other functions which derive from its state but declare its own state too and so on. when migrating this to runes - it's not very clear whats a nice, clean solution

    it may look like this

    function userCardsStore() {
        const cards = writable([]);
    
        return { cards };
    }
    
    function userCreditCardsStore() {
        const creditStatus = writable('new');
    
        const cards = userCardsStore();
        const creditCards = derived(cards.cards, ($cards) => $cards.filter(isCredit));
    
        function updateCreditStatus() {
            if (get(creditCards).length === 0) {
                creditStatus.set('empty');
            } else {
                creditStatus.set('with-cards');
            }
        }
    
        return {
            creditCards,
            creditStatus,
            updateCreditStatus,
        };
    }
    

    assume creditStatus cannot just be a derived and since it needs creditCards, we can't just split these stores - it kinda has to be a stateful derived. And it's a big app so we can't be changing the logic much here so of course ideally there should be a straightfoward way to move store code to rune code.

    I guess the 4th option is to introduce some Rune type { current: T} - akin to what fromStore returns and use that instead of Readable/Writable everywhere

    This probably has been asked before but kinda hard to search for

    This is a duplicate question from Discord: https://discord.com/channels/457912077277855764/1489264519468552294

Loading Svelte Themes