TL;DR
- React でロジックと表示を分けるのに使う Container/Presentational Pattern を、Svelte 5 で書いた。
- 状態の取得と保持は Container 側で
$stateを使い、表示は Presentational 側で$propsから受け取る。
背景
React では、ロジックと表示を別のコンポーネントとして定義するために Container/Presentational Pattern を使う。これを Svelte でも実現したいと思った。Svelte で書いた記事はいくつかあるが、v4 以前のものが多いので、v5 で書くことにした。
検証
コードは patterns.dev の Vue 向けの例を参考にした。犬の画像の URL を API から取得して表示する。
表示だけを担当する Presentational コンポーネントでは、Rune の $props で URL の一覧を受け取る。
<!-- DogImage.svelte -->
<script lang="ts">
const urls = $props()
</script>
{#each urls as url}
<img src={url} alt="Dog" />
{/each}Container コンポーネントでは、$state で URL の一覧を保持し、onMount で API から取得する。
<!-- DogImageContainer.svelte -->
<script lang="ts">
import { onMount } from 'svelte';
const urls = $state([])
const fetchURLs = async () => {
const res = await fetch(
"https://dog.ceo/api/breed/labrador/images/random/6"
)
const { message } = await res.json()
urls.push(...message)
}
onMount(fetchURLs)
</script>
{#each urls as url}
<img src={url} alt="Dog" />
{/each}アプリケーション側では Container を使う。
<!-- App.svelte -->
<script>
import DogImageContainer from './DogImageContainer.svelte'
</script>
<DogImageContainer />考察
ロジックは .svelte.ts ファイルに追い出したい。