SolidJS 入門:最速で Hello World から始める

「SolidJS を試してみたいけど、何から始めればいいの?」そんな疑問にお答えします。
この記事では、SolidJS の基礎知識は最小限に留め、実際に手を動かしながら学習することに重点を置いています。30 分程度で Hello World から始めて、基本的なアプリケーションを作成できるようになることを目指しましょう。
プログラミングを始めたばかりの方でも安心してください。一歩ずつ丁寧に進めていきますので、焦らずに取り組んでみてください。
事前準備
必要な環境の確認
SolidJS の開発を始める前に、以下の環境が整っていることを確認しましょう。
必要なソフトウェア一覧:
# | ソフトウェア | 推奨バージョン | 確認コマンド |
---|---|---|---|
1 | Node.js | 16.14.0 以上 | node --version |
2 | Yarn | 1.22.0 以上 | yarn --version |
3 | Git | 2.25.0 以上 | git --version |
まず、ターミナル(Windows の場合はコマンドプロンプトまたは PowerShell)を開いて、以下のコマンドを実行してください。
bash# Node.jsのバージョン確認
node --version
# Yarnのバージョン確認
yarn --version
# Gitのバージョン確認
git --version
もし Node.js がインストールされていない場合は、Node.js 公式サイトからダウンロードしてインストールしてください。
Yarn がインストールされていない場合は、以下のコマンドでインストールできます:
bash# Yarnのインストール
npm install -g yarn
この時、以下のようなエラーが出る場合があります:
bashnpm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/yarn
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied
このエラーが発生した場合は、管理者権限で実行してください:
bash# macOS/Linuxの場合
sudo npm install -g yarn
# Windowsの場合(PowerShellを管理者権限で実行)
npm install -g yarn
エディタの設定とおすすめ拡張機能
SolidJS の開発には、Visual Studio Code(VS Code)を強くおすすめします。無料で使えて、SolidJS の開発に必要な機能が豊富に揃っています。
VS Code の必須拡張機能:
# | 拡張機能名 | 機能 |
---|---|---|
1 | TypeScript and JavaScript | TypeScript/JavaScript の言語サポート |
2 | ES7+ React/Redux/React-Native | JSX の構文ハイライト |
3 | Auto Rename Tag | HTML タグの自動リネーム |
4 | Bracket Pair Colorizer | 括弧の色分け |
5 | Prettier - Code formatter | コードの自動整形 |
これらの拡張機能をインストールするには、VS Code の左側のサイドバーにある「拡張機能」アイコンをクリックし、上記の名前で検索してインストールしてください。
ステップ 1: プロジェクト作成
yarn create solid でプロジェクト生成
いよいよ SolidJS プロジェクトを作成しましょう。ターミナルを開いて、以下のコマンドを実行してください。
bash# SolidJSプロジェクトの作成
yarn create solid my-first-solid-app
# 作成したディレクトリに移動
cd my-first-solid-app
コマンドを実行すると、以下のような質問が表示されます:
perl? Which template would you like to use? (Use arrow keys)
❯ basic
typescript
tailwindcss
bootstrap
minimal
初心者の方は「basic」を選択してください。TypeScript に慣れている方は「typescript」を選択することもできます。
もし以下のようなエラーが表示された場合:
basherror An unexpected error occurred: "https://registry.yarnpkg.com/create-solid: Not found".
これは Yarn のキャッシュの問題です。以下のコマンドで解決できます:
bash# Yarnキャッシュをクリア
yarn cache clean
# 再度プロジェクト作成を実行
yarn create solid my-first-solid-app
生成されたファイル構造の理解
プロジェクトが正常に作成されたら、以下のような構造になっているはずです。
arduinomy-first-solid-app/
├── public/
│ ├── favicon.ico
│ └── index.html
├── src/
│ ├── App.jsx
│ ├── App.module.css
│ ├── index.jsx
│ └── logo.svg
├── .gitignore
├── package.json
├── vite.config.js
└── yarn.lock
各ファイルの役割を理解しましょう:
# | ファイル/フォルダ | 役割 |
---|---|---|
1 | public/ | 静的ファイル(画像、HTML など)を格納 |
2 | src/ | SolidJS のソースコードを格納 |
3 | src/index.jsx | アプリケーションのエントリーポイント |
4 | src/App.jsx | メインのアプリケーションコンポーネント |
5 | package.json | プロジェクトの依存関係と設定 |
6 | vite.config.js | Vite(ビルドツール)の設定 |
開発サーバーの起動確認
まず、依存関係をインストールして開発サーバーを起動してみましょう。
bash# 依存関係のインストール
yarn install
# 開発サーバーの起動
yarn dev
成功すると、以下のような出力が表示されます:
arduino VITE v4.4.5 ready in 500 ms
➜ Local: http://localhost:3000/
➜ Network: use --host to expose
➜ press h + enter to show help
ブラウザで http://localhost:3000/
にアクセスしてください。SolidJS のデフォルトページが表示されれば成功です!
もし以下のようなエラーが表示された場合:
bashError: listen EADDRINUSE: address already in use :::3000
これは、ポート 3000 が既に使用されていることを意味します。以下のコマンドで別のポートを指定できます:
bash# ポート3001で起動
yarn dev --port 3001
ステップ 2: Hello World の実装
最小限のコンポーネント作成
それでは、独自の Hello World コンポーネントを作成してみましょう。src/App.jsx
ファイルを開いて、以下のように書き換えてください。
jsx// src/App.jsx
function App() {
return (
<div>
<h1>Hello, SolidJS World!</h1>
<p>私の最初の SolidJS アプリケーションです。</p>
</div>
);
}
export default App;
ファイルを保存すると、ブラウザが自動的に更新され、新しい内容が表示されます。これが SolidJS のホットリロード機能です。
JSX の基本記法
SolidJS では JSX という構文を使用します。JSX は JavaScript の中に HTML のような記法を書くことができる構文です。
JSX の基本ルール:
jsx// 正しい書き方
function MyComponent() {
return (
<div>
<h1>タイトル</h1>
<p>段落です</p>
</div>
);
}
// 間違った書き方:複数の要素を返すことはできない
function BadComponent() {
return (
<h1>タイトル</h1>
<p>段落です</p> // エラー!
);
}
もし上記の間違った書き方をすると、以下のようなエラーが表示されます:
javascriptSyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag.
この場合は、要素を <div>
や <>
で囲む必要があります:
jsx// 解決方法1: divで囲む
function MyComponent() {
return (
<div>
<h1>タイトル</h1>
<p>段落です</p>
</div>
);
}
// 解決方法2: フラグメント(<>)で囲む
function MyComponent() {
return (
<>
<h1>タイトル</h1>
<p>段落です</p>
</>
);
}
ブラウザでの表示確認
作成したコンポーネントがブラウザで正しく表示されることを確認しましょう。さらに、開発者ツールの使い方も覚えておくと便利です。
ブラウザで F12
キー(またはマックの場合は Cmd + Option + I
)を押して開発者ツールを開いてください。「Console」タブを確認し、エラーが表示されていないことを確認しましょう。
ステップ 3: 状態管理の基礎
createSignal の使い方
SolidJS では、状態管理に createSignal
を使用します。これが SolidJS の核心的な機能の一つです。
まず、src/App.jsx
を以下のように更新してください:
jsx// src/App.jsx
import { createSignal } from 'solid-js';
function App() {
// 状態の作成
const [count, setCount] = createSignal(0);
return (
<div>
<h1>カウンター: {count()}</h1>
<p>現在の値は {count()} です</p>
</div>
);
}
export default App;
重要なポイントは、count()
というように関数として呼び出すことです。これを忘れると、以下のようなエラーになります:
javascriptTypeError: Cannot read properties of undefined (reading 'toString')
イベントハンドラーの実装
次に、ボタンをクリックしてカウンターを増やす機能を追加しましょう。
jsx// src/App.jsx
import { createSignal } from 'solid-js';
function App() {
const [count, setCount] = createSignal(0);
// イベントハンドラー関数
const increment = () => {
setCount(count() + 1);
};
const decrement = () => {
setCount(count() - 1);
};
return (
<div>
<h1>カウンター: {count()}</h1>
<p>現在の値は {count()} です</p>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
</div>
);
}
export default App;
ボタンをクリックしてみてください。リアルタイムでカウンターの値が変更されることが確認できるはずです。
リアクティブな更新の体験
SolidJS のリアクティブシステムを体験してみましょう。状態が変更されると、自動的に画面が更新されます。
jsx// src/App.jsx
import { createSignal, createMemo } from 'solid-js';
function App() {
const [count, setCount] = createSignal(0);
// 計算された値(メモ化)
const doubleCount = createMemo(() => count() * 2);
const isEven = createMemo(() => count() % 2 === 0);
const increment = () => setCount(count() + 1);
const decrement = () => setCount(count() - 1);
const reset = () => setCount(0);
return (
<div style={{ padding: '20px', font: 'Arial' }}>
<h1>SolidJS カウンター</h1>
<div style={{ margin: '20px 0' }}>
<h2>現在の値: {count()}</h2>
<p>2倍の値: {doubleCount()}</p>
<p>偶数かどうか: {isEven() ? '偶数' : '奇数'}</p>
</div>
<div>
<button
onClick={increment}
style={{ margin: '5px' }}
>
+1
</button>
<button
onClick={decrement}
style={{ margin: '5px' }}
>
-1
</button>
<button onClick={reset} style={{ margin: '5px' }}>
リセット
</button>
</div>
</div>
);
}
export default App;
この例では、count
の値が変更されると、doubleCount
と isEven
も自動的に再計算されます。これが SolidJS のリアクティブシステムの威力です。
ステップ 4: コンポーネント間の連携
Props の受け渡し
複数のコンポーネントを作成し、データを受け渡してみましょう。新しいファイル src/Counter.jsx
を作成してください。
jsx// src/Counter.jsx
function Counter(props) {
return (
<div
style={{
border: '1px solid #ccc',
padding: '10px',
margin: '10px',
}}
>
<h3>{props.title}</h3>
<p>現在の値: {props.value}</p>
<button onClick={props.onIncrement}>+1</button>
<button onClick={props.onDecrement}>-1</button>
</div>
);
}
export default Counter;
子コンポーネントの作成
次に、src/App.jsx
を更新して、作成した Counter
コンポーネントを使用しましょう。
jsx// src/App.jsx
import { createSignal } from 'solid-js';
import Counter from './Counter';
function App() {
const [count1, setCount1] = createSignal(0);
const [count2, setCount2] = createSignal(10);
return (
<div style={{ padding: '20px' }}>
<h1>複数のカウンター</h1>
<Counter
title='カウンター1'
value={count1()}
onIncrement={() => setCount1(count1() + 1)}
onDecrement={() => setCount1(count1() - 1)}
/>
<Counter
title='カウンター2'
value={count2()}
onIncrement={() => setCount2(count2() + 2)}
onDecrement={() => setCount2(count2() - 2)}
/>
<div style={{ marginTop: '20px' }}>
<h3>合計: {count1() + count2()}</h3>
</div>
</div>
);
}
export default App;
コンポーネントの再利用
同じ Counter
コンポーネントを、異なる props で複数回使用していることがわかります。これがコンポーネントの再利用性の利点です。
もし props の名前を間違えると、以下のようなエラーが発生する可能性があります:
javascriptTypeError: Cannot read properties of undefined (reading 'title')
このエラーが発生した場合は、props の名前が正しいかどうか確認してください。
ステップ 5: 実用的な機能の追加
条件付きレンダリング
条件によって異なる内容を表示する機能を実装してみましょう。src/App.jsx
を以下のように更新してください。
jsx// src/App.jsx
import { createSignal, Show } from 'solid-js';
function App() {
const [count, setCount] = createSignal(0);
const [showDetails, setShowDetails] = createSignal(false);
const increment = () => setCount(count() + 1);
const decrement = () => setCount(count() - 1);
const toggleDetails = () =>
setShowDetails(!showDetails());
return (
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<h1>条件付きレンダリング</h1>
<div style={{ margin: '20px 0' }}>
<h2>カウンター: {count()}</h2>
{/* 条件付きレンダリング方法1: 三項演算子 */}
<p>{count() > 0 ? '正の数です' : '0以下です'}</p>
{/* 条件付きレンダリング方法2: Show コンポーネント */}
<Show when={count() > 10}>
<p style={{ color: 'red', fontWeight: 'bold' }}>
カウンターが10を超えました!
</p>
</Show>
<Show when={count() < 0}>
<p style={{ color: 'blue' }}>
カウンターがマイナスです
</p>
</Show>
</div>
<div style={{ margin: '20px 0' }}>
<button
onClick={increment}
style={{ margin: '5px' }}
>
+1
</button>
<button
onClick={decrement}
style={{ margin: '5px' }}
>
-1
</button>
<button
onClick={toggleDetails}
style={{ margin: '5px' }}
>
{showDetails() ? '詳細を隠す' : '詳細を表示'}
</button>
</div>
<Show when={showDetails()}>
<div
style={{
border: '1px solid #ddd',
padding: '15px',
}}
>
<h3>詳細情報</h3>
<p>現在の値: {count()}</p>
<p>絶対値: {Math.abs(count())}</p>
<p>2乗: {count() * count()}</p>
<p>
偶数: {count() % 2 === 0 ? 'はい' : 'いいえ'}
</p>
</div>
</Show>
</div>
);
}
export default App;
リスト表示とループ処理
次に、リストを表示してループ処理を実装してみましょう。
jsx// src/App.jsx
import { createSignal, For } from 'solid-js';
function App() {
const [items, setItems] = createSignal([
{ id: 1, name: 'リンゴ', price: 150 },
{ id: 2, name: 'バナナ', price: 100 },
{ id: 3, name: 'オレンジ', price: 200 },
]);
const [newItemName, setNewItemName] = createSignal('');
const [newItemPrice, setNewItemPrice] = createSignal('');
const addItem = () => {
const name = newItemName().trim();
const price = parseInt(newItemPrice());
if (name && price > 0) {
const newItem = {
id: Date.now(),
name: name,
price: price,
};
setItems([...items(), newItem]);
setNewItemName('');
setNewItemPrice('');
}
};
const removeItem = (id) => {
setItems(items().filter((item) => item.id !== id));
};
const totalPrice = () => {
return items().reduce(
(sum, item) => sum + item.price,
0
);
};
return (
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<h1>商品リスト</h1>
{/* 新しいアイテムの追加 */}
<div
style={{
marginBottom: '20px',
border: '1px solid #ddd',
padding: '15px',
}}
>
<h3>新しい商品を追加</h3>
<div style={{ marginBottom: '10px' }}>
<input
type='text'
placeholder='商品名'
value={newItemName()}
onInput={(e) => setNewItemName(e.target.value)}
style={{ marginRight: '10px', padding: '5px' }}
/>
<input
type='number'
placeholder='価格'
value={newItemPrice()}
onInput={(e) => setNewItemPrice(e.target.value)}
style={{ marginRight: '10px', padding: '5px' }}
/>
<button
onClick={addItem}
style={{ padding: '5px 10px' }}
>
追加
</button>
</div>
</div>
{/* 商品リストの表示 */}
<div>
<h3>商品一覧(合計: {totalPrice()}円)</h3>
<For each={items()}>
{(item) => (
<div
style={{
border: '1px solid #ccc',
padding: '10px',
margin: '5px 0',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div>
<strong>{item.name}</strong> - {item.price}
円
</div>
<button
onClick={() => removeItem(item.id)}
style={{
backgroundColor: '#ff4444',
color: 'white',
border: 'none',
padding: '5px 10px',
cursor: 'pointer',
}}
>
削除
</button>
</div>
)}
</For>
</div>
</div>
);
}
export default App;
フォーム入力の処理
フォームの入力処理について、より詳しく学んでみましょう。
jsx// src/App.jsx
import { createSignal } from 'solid-js';
function App() {
const [formData, setFormData] = createSignal({
name: '',
email: '',
age: '',
gender: '',
interests: [],
});
const [errors, setErrors] = createSignal({});
const handleInputChange = (field, value) => {
setFormData({
...formData(),
[field]: value,
});
// エラーをクリア
if (errors()[field]) {
setErrors({
...errors(),
[field]: undefined,
});
}
};
const handleCheckboxChange = (interest, checked) => {
const currentInterests = formData().interests;
let newInterests;
if (checked) {
newInterests = [...currentInterests, interest];
} else {
newInterests = currentInterests.filter(
(i) => i !== interest
);
}
setFormData({
...formData(),
interests: newInterests,
});
};
const validateForm = () => {
const newErrors = {};
const data = formData();
if (!data.name.trim()) {
newErrors.name = '名前は必須です';
}
if (!data.email.trim()) {
newErrors.email = 'メールアドレスは必須です';
} else if (!/\S+@\S+\.\S+/.test(data.email)) {
newErrors.email =
'メールアドレスの形式が正しくありません';
}
if (!data.age || data.age < 0 || data.age > 150) {
newErrors.age = '年齢は0-150の範囲で入力してください';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validateForm()) {
console.log('フォームデータ:', formData());
alert('フォームが正常に送信されました!');
}
};
return (
<div
style={{
padding: '20px',
fontFamily: 'Arial',
maxWidth: '600px',
}}
>
<h1>ユーザー登録フォーム</h1>
<form onSubmit={handleSubmit}>
{/* 名前 */}
<div style={{ marginBottom: '15px' }}>
<label
style={{
display: 'block',
marginBottom: '5px',
}}
>
名前 <span style={{ color: 'red' }}>*</span>
</label>
<input
type='text'
value={formData().name}
onInput={(e) =>
handleInputChange('name', e.target.value)
}
style={{
width: '100%',
padding: '8px',
border: errors().name
? '1px solid red'
: '1px solid #ccc',
}}
/>
{errors().name && (
<div
style={{
color: 'red',
fontSize: '12px',
marginTop: '5px',
}}
>
{errors().name}
</div>
)}
</div>
{/* メールアドレス */}
<div style={{ marginBottom: '15px' }}>
<label
style={{
display: 'block',
marginBottom: '5px',
}}
>
メールアドレス{' '}
<span style={{ color: 'red' }}>*</span>
</label>
<input
type='email'
value={formData().email}
onInput={(e) =>
handleInputChange('email', e.target.value)
}
style={{
width: '100%',
padding: '8px',
border: errors().email
? '1px solid red'
: '1px solid #ccc',
}}
/>
{errors().email && (
<div
style={{
color: 'red',
fontSize: '12px',
marginTop: '5px',
}}
>
{errors().email}
</div>
)}
</div>
{/* 年齢 */}
<div style={{ marginBottom: '15px' }}>
<label
style={{
display: 'block',
marginBottom: '5px',
}}
>
年齢
</label>
<input
type='number'
value={formData().age}
onInput={(e) =>
handleInputChange(
'age',
parseInt(e.target.value) || 0
)
}
style={{
width: '100%',
padding: '8px',
border: errors().age
? '1px solid red'
: '1px solid #ccc',
}}
/>
{errors().age && (
<div
style={{
color: 'red',
fontSize: '12px',
marginTop: '5px',
}}
>
{errors().age}
</div>
)}
</div>
{/* 性別 */}
<div style={{ marginBottom: '15px' }}>
<label
style={{
display: 'block',
marginBottom: '5px',
}}
>
性別
</label>
<div>
<label style={{ marginRight: '15px' }}>
<input
type='radio'
name='gender'
value='male'
checked={formData().gender === 'male'}
onChange={(e) =>
handleInputChange(
'gender',
e.target.value
)
}
/>
男性
</label>
<label style={{ marginRight: '15px' }}>
<input
type='radio'
name='gender'
value='female'
checked={formData().gender === 'female'}
onChange={(e) =>
handleInputChange(
'gender',
e.target.value
)
}
/>
女性
</label>
<label>
<input
type='radio'
name='gender'
value='other'
checked={formData().gender === 'other'}
onChange={(e) =>
handleInputChange(
'gender',
e.target.value
)
}
/>
その他
</label>
</div>
</div>
{/* 興味のある分野 */}
<div style={{ marginBottom: '15px' }}>
<label
style={{
display: 'block',
marginBottom: '5px',
}}
>
興味のある分野(複数選択可)
</label>
<div>
{[
'プログラミング',
'デザイン',
'マーケティング',
'データ分析',
].map((interest) => (
<label
key={interest}
style={{
display: 'block',
marginBottom: '5px',
}}
>
<input
type='checkbox'
checked={formData().interests.includes(
interest
)}
onChange={(e) =>
handleCheckboxChange(
interest,
e.target.checked
)
}
/>
{interest}
</label>
))}
</div>
</div>
<button
type='submit'
style={{
backgroundColor: '#007bff',
color: 'white',
padding: '10px 20px',
border: 'none',
cursor: 'pointer',
fontSize: '16px',
}}
>
送信
</button>
</form>
{/* デバッグ用: 現在のフォームデータを表示 */}
<div
style={{
marginTop: '30px',
padding: '15px',
backgroundColor: '#f5f5f5',
}}
>
<h3>現在のフォームデータ</h3>
<pre>{JSON.stringify(formData(), null, 2)}</pre>
</div>
</div>
);
}
export default App;
よくあるエラーと解決法
初心者が遭遇しやすい問題
SolidJS を学習する際によく遭遇するエラーとその解決法をまとめました。
エラー 1: Signal を関数として呼び出していない
bashTypeError: Cannot read properties of undefined (reading 'toString')
原因: createSignal
で作成した状態を関数として呼び出していない
jsx// ❌ 間違い
const [count, setCount] = createSignal(0);
return <div>{count}</div>;
// ✅ 正しい
const [count, setCount] = createSignal(0);
return <div>{count()}</div>;
エラー 2: JSX 要素の不正な構造
bashSyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag.
原因: 複数の JSX 要素を返す際に、ラッパー要素で囲んでいない
jsx// ❌ 間違い
function MyComponent() {
return (
<h1>タイトル</h1>
<p>内容</p>
);
}
// ✅ 正しい
function MyComponent() {
return (
<div>
<h1>タイトル</h1>
<p>内容</p>
</div>
);
}
エラー 3: Import 文の間違い
bashModule not found: Error: Can't resolve './Counter'
原因: ファイルの拡張子を省略しているか、パスが間違っている
jsx// ❌ 間違い(拡張子がない場合)
import Counter from './Counter';
// ✅ 正しい
import Counter from './Counter.jsx';
エラー 4: 依存関係の問題
bashError: Cannot resolve dependency tree
npm ERR! ERESOLVE unable to resolve dependency tree
解決法:
bash# node_modulesを削除
rm -rf node_modules yarn.lock
# 依存関係を再インストール
yarn install
# または、キャッシュをクリア
yarn cache clean
yarn install
エラー 5: ポートの競合
bashError: listen EADDRINUSE: address already in use :::3000
解決法:
bash# 別のポートを使用
yarn dev --port 3001
# または、プロセスを強制終了
# macOS/Linux
lsof -ti:3000 | xargs kill -9
# Windows
netstat -ano | findstr :3000
taskkill /PID <PID番号> /F
デバッグのコツ
1. ブラウザの開発者ツールを活用する
F12
キーまたはCmd + Option + I
で開発者ツールを開く- Console タブでエラーメッセージを確認
- Network タブでファイルの読み込み状況を確認
2. コンソールでの値の確認
jsx// 状態の値を確認
const [count, setCount] = createSignal(0);
// コンソールに出力
console.log('現在のカウント:', count());
// 関数内でのデバッグ
const handleClick = () => {
console.log('ボタンがクリックされました');
setCount(count() + 1);
console.log('新しいカウント:', count());
};
3. 段階的な実装
問題が発生した場合は、以下の手順で段階的に確認してください:
- 最小限のコードで動作を確認
- 一つずつ機能を追加
- 各段階でテスト
- エラーが発生した箇所を特定
4. 公式ドキュメントとコミュニティの活用
まとめ
お疲れさまでした!この記事を通じて、SolidJS の基本的な使い方を学ぶことができました。
習得できた内容:
# | 内容 | 重要度 |
---|---|---|
1 | 開発環境のセットアップ | ★★★ |
2 | プロジェクトの作成 | ★★★ |
3 | 基本的なコンポーネント | ★★★ |
4 | 状態管理(createSignal) | ★★★ |
5 | イベントハンドリング | ★★★ |
6 | コンポーネント間連携 | ★★ |
7 | 条件付きレンダリング | ★★ |
8 | リスト表示とループ | ★★ |
9 | フォーム処理 | ★★ |
10 | エラーハンドリング | ★ |
次のステップ:
- ルーティング: SolidJS Router を使用してページ遷移を実装
- 状態管理: より複雑な状態管理ライブラリの学習
- API 連携: 外部 API との通信処理
- スタイリング: CSS-in-JS や Tailwind CSS の活用
- テスト: Jest や Vitest を使用したテスト作成
- デプロイ: Vercel や Netlify への本番環境デプロイ
SolidJS は学習しやすく、パフォーマンスも優秀なフレームワークです。ぜひ実際のプロジェクトでも活用してみてください。
何か問題が発生した場合は、この記事のエラー解決法を参考にしながら、一歩ずつ解決していきましょう。プログラミングは試行錯誤の連続ですが、それが上達への近道です。
関連リンク
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来
- review
人類はなぜ地球を支配できた?『サピエンス全史 上巻』ユヴァル・ノア・ハラリが解き明かす驚愕の真実
- review
え?世界はこんなに良くなってた!『FACTFULNESS』ハンス・ロスリングが暴く 10 の思い込みの正体
- review
瞬時に答えが出る脳に変身!『ゼロ秒思考』赤羽雄二が贈る思考力爆上げトレーニング
- review
関西弁のゾウに人生変えられた!『夢をかなえるゾウ 1』水野敬也が教えてくれた成功の本質
- review
「なぜ私の考えは浅いのか?」の答えがここに『「具体 ⇄ 抽象」トレーニング』細谷功