はじめに
第6章でバックエンドと連携しました。今回は、TypeScriptでコードを安全にし、Vitestでテストを追加します。これでアプリの信頼性と保守性が向上します。
目標
- TypeScriptをViteに統合する
- Vitestでユニットテストを実装する
- ToDoアプリを強化する
TypeScriptの導入
1. TypeScriptプロジェクトへの移行
既存プロジェクトをTypeScriptに変換:
npm install typescript @types/react @types/react-dom --save-dev
- プロジェクト作成時に
--template react-ts
を選んだ場合は不要。
tsconfig.json
がなければ、生成:
npx tsc --init
vite.config.js
をvite.config.ts
に変更:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
2. App.tsxへの変換
src/App.jsx
をsrc/App.tsx
にリネームし、型を追加:
import { useState, useEffect } from 'react';
import './App.css';
interface Todo {
id: number;
text: string;
}
function App() {
const [todos, setTodos] = useState<Todo[]>([]);
const [input, setInput] = useState<string>('');
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
fetchTodos();
}, []);
const fetchTodos = async () => {
try {
const response = await fetch('/api/todos');
const data: Todo[] = await response.json();
setTodos(data);
} catch (error) {
console.error('エラー:', error);
} finally {
setLoading(false);
}
};
const addTodo = async (e: React.FormEvent) => {
e.preventDefault();
if (!input) return;
try {
const response = await fetch('/api/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: input }),
});
const newTodo: Todo = await response.json();
setTodos([...todos, newTodo]);
setInput('');
} catch (error) {
console.error('追加エラー:', error);
}
};
if (loading) return <div>読み込み中...</div>;
return (
<div className="App">
<header>
<h1>{import.meta.env.VITE_APP_TITLE}</h1>
</header>
<main>
<form onSubmit={addTodo}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="タスクを入力"
/>
<button type="submit">追加</button>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</main>
</div>
);
}
export default App;
Vitestの導入
1. インストール
npm install vitest jsdom @testing-library/react @testing-library/jest-dom --save-dev
2. 設定
vite.config.ts
にテスト設定を追加:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
test: {
environment: 'jsdom',
globals: true,
setupFiles: './src/test/setup.ts',
},
});
src/test/setup.ts
を作成:
import '@testing-library/jest-dom';
package.json
にスクリプトを追加:
"scripts": {
"test": "vitest"
}
3. テストの実装
src/App.test.tsx
を作成:
import { render, screen, fireEvent } from '@testing-library/react';
import App from './App';
describe('App', () => {
it('タスクを追加できる', async () => {
render(<App />);
await screen.findByText('私のToDoアプリ'); // タイトルが表示されるまで待機
const input = screen.getByPlaceholderText('タスクを入力');
const button = screen.getByText('追加');
fireEvent.change(input, { target: { value: 'テストタスク' } });
fireEvent.click(button);
expect(await screen.findByText('テストタスク')).toBeInTheDocument();
});
});
- バックエンド依存のため、モックが必要な場合も考慮。
動作確認
- TypeScript:
npm run dev
でエラーがないか確認。 - テスト:
npm test
でテストを実行。
次回予告
第8章でシリーズを総括し、次の学習ステップを提案します。お楽しみに!
この記事が役に立ったら、ぜひ「いいね」や「ストック」をお願いします!質問や感想はコメント欄で気軽にどうぞ。次回も一緒に学びましょう!