Back
TABLE OF CONTENTS
If you are used to React, component structures in Astro (and Svelte) can feel somewhat limiting asit is more markup-oriented. One thing I often miss when writing Astro components is the ability todo an early exit. Meaning this:
functionMyComponent() {if (someCondition) {return <h1>Not found</h1>;}return <>Larger stuff over here</>;}
There are several schools of thoughts on doing early exits in components and functions in general,but for me it always makes it easier to cognitively clean up. As in “now I’m done with this, fromhere on out, don’t think about it”. You can also do this without an early exit:
functionMyComponent() {return <>{someCondition? <h1>Not found</h1>: <>Larger stuff over here</>}</>;}
But for me, this doesn’t make it so I don’t have to think about it as a) it is more syntacticallyintertwined, and b) indents the code making it visibly affected. But this is what you’d have to doin Astro as this is not possible:
---// some setup---{someCondition&& (return <h1>Not found</h1>)}
You would always have to do this:
---// some setupt---{someCondition? <h1>Not found</h1>: <>Larger stuff over here</>}
Not a big issue, but for cases where you want to show something or nothing at all, I find itdistracting:
---// some setupt---{someCondition&& <>Larger stuff over here</>}
This is especially apparent when having lists that can be empty:
{items.length===0?<p>No items</p>: (<ul>{items.map(_item=> <li />)}</ul>)}
God forbid having nested lists.
The Helpers
We can make this less noisy with simple helper components. Nothing magical or revolutionary, butjust a reminder that creating helper components is useful.
Null or show
Show something only if it is defined
---interfaceProps<T> {data:T;}const {data }= Astro.props;---{!data? <></>: <slot />}
Empty list or show
Particularly handy as you often want to have wrapping container around lists:
---interfaceProps {items?:any[];}const {items }= Astro.props;---{items.length==0? <></>: <slot />}
Usage:
<EmptyOrSlotitems={myItems}><ul>{myItems.map(()=> <li></li>)}</ul></EmptyOrSlot>
This can be done even more handy by adding several slots:
---interfaceProps {items?:any[];}const {items }= Astro.props;---{items.length==0? <slotname="empty" />: <slot />}
Usage:
<EmptyOrSlotitems={myItems}><pslot="empty">No items</p><ul>{myItems.map(()=> <li></li>)}</ul></EmptyOrSlot>
Making use of multiple slots like this is very flexible as you can control whattype of content to show without limiting to just doing strings.
<EmptyOrSlotitems={myItems}><SomeSuperFancyMessageBoxslot="empty" /><ul>{myItems.map(()=> <li></li>)}</ul></EmptyOrSlot>