'Svelte if block's behavior is different form component's property when is set to undefined
I prefer to define a visible property for Svelte components rather than writing Svelte's if block in template. In my opinion, it is more clean to set a visible property instead of adding 2 lines of if block codes in the template.
I am trying to define a visible property for a Svelte component which must have the same behavior of if block.
El.svelte
<script>
export let visible = true // should be visible by default
</script>
{#if visible}
<svelte:element this="div" {...$$restProps}>
<slot />
</svelte:element>
{/if}
App.svelte
<script>
import El from './El.svelte';
let visible = undefined
</script>
<El {visible}>Component (undefined)</El>
{#if visible}
Svelte if block (undefined)
{/if}
The if block is working as expected, but the component is rendered which shouldn't be.
It seems that undefined property isn't passed to component during Svelte compilation.
What is the best way to make consistent behavior for visible property?
Update:
The reason I want to use as visible property is the final code is more readable. Here is a sample code using if block:
{#if invoice.payment}
{#if invoice.payment?.approved}
<Badge>Approved</Badge>
{#if !order.confirmed}
<Button>Void Payment</Button>
{/if}
{/if}
{#if invoice.payment?.status }
<b>{invoice.payment.tranasction.id}</b>
{/if}
{/if}
And using visible property:
<Div visible={invoice.payment?.approved}>
<Badge>Approved</Badge>
<Button visible={!order.confirmed}>Void Payment</Button>
</Div>
<B visible={invoice.payment?.status}>{invoice.payment.tranasction.id}</B>
The updated repl to support all scenarios.
But I'm not sure if it's correct implementation or future usage in nested components and event/property/action bindings.
Update 2:
I don't think this is a my-opinion-based usage: Vue.js has v-if and
Angular has ng-if that does the same thing as visible.
Solution 1:[1]
If you really want to stick with this approach (which I would not recommend - just use {#if} when you need it), then the best way to deal with this might be to not allow undefined to ever be passed as a value, because that resolves to the default set in the component (in this case visible = true).
So if you have a value that is potentially undefined, make sure it resolves to either true or false, e.g.
<El visible={visible ?? false}>
Edit in response to question update: Using property inspection is indeed a working approach, though I would not allow arbitrary values, only boolean, null or undefined. The simplest setup for this would be:
export let visible = undefined;
if ('visible' in $$props == false)
visible = true;
A reactive statement is not required in this case, because whether a property is defined at all does not change. (This requires setting visible={false} instead of visible="false".)
One reason to not do this at all is the use of $$restProps, as the docs state:
It shares the same optimisation problems as
$$props, and is likewise not recommended.
Also, you will run into issues if you want to do event handling.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
