Introduction
こんにちわ、milkyskiesだよ♪
Svelte 5の講座を始めるよ♪
React厨の皆様ならば1時間で覚えられるね♪
使われる技術
React
- NextJS (App Router)
- TypeScript
- Tailwind CSS
Svelte 5
- SvelteKit
- TypeScript
- Tailwind CSS
State
Stateの基本
React | Svelte 5 |
---|---|
useState |
$state |
React
import React, { useState } from "react";
export default function Page() {
const [name, setName] = useState("太郎");
return (
<p>
こんにちは、{name}!
</p>
);
}
Svelte 5
<script lang="ts">
let name = $state("太郎");
</script>
<p>
こんにちは、 {name}!
</p>
Stateの変更
ついでにuseEffect
のSvelte 5版も紹介するよ!
React | Svelte 5 |
---|---|
setName("次郎") |
name = "次郎" |
useEffect |
$effect |
React
import React, { useState, useEffect } from "react";
export default function Page() {
const [name, setName] = useState("太郎");
useEffect(() => {
setName("次郎");
}, []);
return (
<p>
こんにちは、{name}!
</p>
);
}
Svelte 5
<script lang="ts">
let name = $state("太郎");
$effect(() => {
name = "次郎";
});
</script>
<p>
こんにちは、 {name}!
</p>
ボタンでstateを変更
SvelteではonClick
じゃなくてonclick
だよ!本来のHTMLと一緒だよ!
React | Svelte 5 |
---|---|
onClick |
onclick |
React
import React, { useState, useEffect } from "react";
export default function Page() {
const [count, setCount] = useState(0);
function increaseCount(amount: number) {
setCount((count) => count + amount);
}
return (
<>
<p>count: {count}</p>
<button onClick={() => increaseCount(1)}>countを増やす</button>
</>
);
}
Svelte 5
<script lang="ts">
let count = $state(0);
function increaseCount(amount: number) {
count += amount;
}
</script>
<p>count: {count}</p>
<button onclick={() => increaseCount(1)}>countを増やす</button>
入力欄でリアルタイムでstateを更新
ここに関しては、ReactとSvelteがかなり違ってくる。
個人的にはSvelteのほうが圧倒的に書きやすいと思う。
React | Svelte 5 |
---|---|
onChange |
bind |
React
import React, { ChangeEvent, useState } from "react";
export default function Page() {
const [name, setName] = useState("");
function handleInputChange(event: ChangeEvent<HTMLInputElement>) {
setName(event.target.value);
}
return (
<>
<input onChange={handleInputChange}>
<p>こんにちは、{name}!</p>
</>
);
}
Svelte 5
<script lang="ts">
let name = $state("");
</script>
<input bind:value={name}>
<p>こんにちは、{name}!</p>
Components
Componentの作成
ついでにTailwindの使い方も少し紹介するよ!
React | Svelte 5 |
---|---|
className |
class |
別ファイルでcomponentを作成する方法
React
type CardProps = {
title: string
text: string
};
export function Card({ title, text }: CardProps) {
return (
<div className="bg-slate-200 h-screen w-screen flex items-center justify-center">
<div className="bg-white shadow-2xl rounded-lg w-96 min-h-32 p-4">
<h2 className="text-2xl font-bold">{title}</h2>
<p className="text-slate-500 mt-2">{text}</p>
</div>
</div>
);
}
import { Card } from '@/components/card';
export default function Page() {
return (
<Card title="カード" text="こんにちは!" />
);
}
Svelte 5
<script lang="ts">
type CardProps = {
title: string
text: string
};
let { title, text }: CardProps = $props();
</script>
<div class="bg-slate-200 h-screen w-screen flex items-center justify-center">
<div class="bg-white shadow-2xl rounded-lg w-96 min-h-32 p-4">
<h2 class="text-2xl font-bold">{title}</h2>
<p class="text-slate-500 mt-2">{text}</p>
</div>
</div>
<script lang="ts">
import Card from '@components/card.svelte';
</script>
<Card title="カード" text="こんにちは!" />
同じファイルでcomponentを作る方法
React
type CardProps = {
title: string
text: string
};
function Card({ title, text }: CardProps) {
return (
<div className="bg-slate-200 h-screen w-screen flex items-center justify-center">
<div className="bg-white shadow-2xl rounded-lg w-96 min-h-32 p-4">
<h2 className="text-2xl font-bold">{title}</h2>
<p className="text-slate-500 mt-2">{text}</p>
</div>
</div>
);
}
export default function Page() {
return (
<Card title="カード" text="こんにちは!" />
);
}
Svelte 5
こっちはあまりおすすめしないかも!Componentを作るときはだいたい上記みたいに別ファイルで作りましょう!
<script lang="ts">
type CardProps = {
title: string;
text: string;
};
</script>
{#snippet card({ title, text }: CardProps)}
<div class="bg-slate-200 h-screen w-screen flex items-center justify-center">
<div class="bg-white shadow-2xl rounded-lg w-96 min-h-32 p-4">
<h2 class="text-2xl font-bold">{title}</h2>
<p class="text-slate-500 mt-2">{text}</p>
</div>
</div>
{/snippet}
<div class="bg-slate-2000 h-screen w-screen flex items-center justify-center">
{@render card({ title: 'カード', text: 'こんにちは!' })}
</div>
現時点(2024-08-13)、Svelte 5のコードブロックはまだQiitaに完全対応されていないようなので、コードブロックにエラーが出ていますが、コード自体は大丈夫です。
Componentにcomponentを渡す方法
Reactと同じく、一つの引数をchildren
と名付けるとcomponentの中にcomponentを入れられるようになる!
children
じゃなくてもいいけど、Reactと同じくその場合は他のpropと同じように渡さないといけなくなるから注意!
React | Svelte 5 |
---|---|
ReactNode |
Snippet |
React
import { ReactNode } from 'react';
type CardProps = {
title: string
children: ReactNode
};
export function Card({ title, children }: CardProps) {
return (
<div className="bg-slate-200 h-screen w-screen flex items-center justify-center">
<div className="bg-white shadow-2xl rounded-lg w-96 min-h-32 p-4">
<h2 className="text-2xl font-bold">{title}</h2>
<div className="text-slate-500 mt-2">
{children}
</div>
</div>
</div>
);
}
import { Card } from '@/components/card';
export default function Page() {
return (
<Card title="カード">
<p>こんにちは!</p>
</Card>
);
}
Svelte 5
<script lang="ts">
import type { Snippet } from 'svelte';
type CardProps = {
title: string;
children: Snippet;
};
let { title, children }: CardProps = $props();
</script>
<div class="bg-slate-200 h-screen w-screen flex items-center justify-center">
<div class="bg-white shadow-2xl rounded-lg w-96 min-h-32 p-4">
<h2 class="text-2xl font-bold">{title}</h2>
<p class="text-slate-500 mt-2">
{@render children()}
</p>
</div>
</div>
<script lang="ts">
import Card from '@components/card.svelte';
</script>
<Card title="カード">
<p>こんにちは!</p>
</Card>
HTMLElementを継承してComponentを作る方法
React
import { ButtonHTMLAttributes } from 'react';
type ButtonProps = {
label: string;
className?: string;
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
export const Button = ({ label, className, ...restProps }: ButtonProps) => {
return (
<button type="button" className={`bg-blue-500 text-white px-4 py-2 rounded-md ${className}`} {...restProps}>
{label}
</button>
);
};
Svelte 5
<script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
type ButtonProps = {
label: string;
class?: string;
} & HTMLButtonAttributes;
let { label, class: className, ...restProps }: ButtonProps = $props();
</script>
<button class={`bg-blue-500 text-white px-4 py-2 rounded-md ${className}`} {...restProps}>
{label}
</button>
現時点(2024-08-13)、Svelte 5のコードブロックはまだQiitaに完全に対応されていないようなので、コードブロックにエラーが出ていますが、コード自体は大丈夫です。
まとめ
いかがでしたか!Svelte 5はSvelte 4と比較すると、よりReactっぽい書き方になっている感じするね!
次回は、Svelteの条件分岐やループなどの紹介もしていきたいと思います。
ほな!