These posts are aggregated from Svelte GitHub Repository.
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
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()}
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?
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?
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:
bind: for simple/local stateonChange for async/server-backed updatesOr is it better to encourage only a single pattern consistently across the component API?
Would appreciate any guidance or examples from Svelte community.
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?
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}
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
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