React、TypeScript、Axios を使った高パフォーマンスな Web アプリケーションの構築
React、TypeScript、Axios を使った API 呼び出しと型定義
- React は、Web アプリケーションの構築に使用される JavaScript ライブラリです。
- TypeScript は、JavaScript の型付けスーパーセット言語です。
- Axios は、JavaScript で HTTP リクエストを作成するためのライブラリです。
API 呼び出し
Axios を使用して API を呼び出すには、次のコードを使用します。
import axios from 'axios';
const fetchData = async () => {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1');
const data = response.data;
console.log(data);
} catch (error) {
console.error(error);
}
};
fetchData();
このコードは、https://jsonplaceholder.typicode.com/todos/1
エンドポイントに GET リクエストを送信し、レスポンスをコンソールに出力します。
型定義
TypeScript を使用して API レスポンスを型定義するには、次のコードを使用します。
interface Todo {
id: number;
userId: number;
title: string;
completed: boolean;
}
const fetchData = async () => {
try {
const response = await axios.get<Todo>('https://jsonplaceholder.typicode.com/todos/1');
const data = response.data;
console.log(data);
} catch (error) {
console.error(error);
}
};
fetchData();
このコードでは、Todo
インターフェースを定義して、API レスポンスの構造を記述しています。fetchData
関数は、Todo
型のジェネリック型パラメータを使用して、axios.get
メソッドの戻り値を型指定しています。
TypeScript を使用して API レスポンスを型定義することで、コードの読みやすさと保守性を向上させることができます。また、コンパイル時の型チェックによって、潜在的なエラーを早期に発見することができます。
- TypeScript の型システムは非常に強力ですが、学習曲線が少しあります。TypeScript を初めて使用する場合は、チュートリアルやドキュメントを参照することをお勧めします。
src
├── App.tsx
├── components
│ └── TodoList.tsx
├── hooks
│ └── useFetchTodos.ts
├── index.tsx
└── styles.css
コード解説
1 App.tsx
import React from 'react';
import TodoList from './components/TodoList';
import useFetchTodos from './hooks/useFetchTodos';
const App: React.FC = () => {
const { todos, isLoading, error } = useFetchTodos();
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>{error.message}</div>;
}
return <TodoList todos={todos} />;
};
export default App;
このコンポーネントは、useFetchTodos
カスタムフックを使用して API から Todo データを取得し、TodoList
コンポーネントに渡します。
2 TodoList.tsx
import React from 'react';
interface Todo {
id: number;
userId: number;
title: string;
completed: boolean;
}
const TodoList: React.FC<Props<Todo[]>> = ({ todos }) => {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
{todo.title} ({todo.completed ? '完了' : '未完了'})
</li>
))}
</ul>
);
};
export default TodoList;
このコンポーネントは、Todo
インターフェースを使用して Todo データの型を定義し、todos
プロップとして受け取った Todo データのリストをレンダリングします。
3 useFetchTodos.ts
import React, { useState, useEffect } from 'react';
import axios from 'axios';
interface Todo {
id: number;
userId: number;
title: string;
completed: boolean;
}
const useFetchTodos = () => {
const [todos, setTodos] = useState<Todo[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos');
const data = response.data as Todo[];
setTodos(data);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
};
fetchData();
}, []);
return { todos, isLoading, error };
};
export default useFetchTodos;
このカスタムフックは、useEffect
フックを使用して https://jsonplaceholder.typicode.com/todos
エンドポイントに GET リクエストを送信し、レスポンスを todos
ステートに格納します。また、isLoading
と error
ステートを使用して、データの読み込み状態とエラーを管理します。
4 index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
このファイルは、React アプリケーションのルート要素をレンダリングします。
5 styles.css
/* スタイル定義 */
このファイルは、アプリケーションのスタイルを定義します。
実行
このコードを実行するには、次のコマンドを実行します。
npm start
Axios リクエストインターセプターを使用して、リクエストの型を指定することができます。
import axios from 'axios';
axios.interceptors.request.use(
(config) => {
if (config.method === 'get' && config.url === 'https://jsonplaceholder.typicode.com/todos/1') {
config.headers['Accept'] = 'application/json';
config.responseType = 'json';
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
このコードは、https://jsonplaceholder.typicode.com/todos/1
エンドポイントへの GET リクエストに対して、Accept
ヘッダーを application/json
に設定し、応答の型を json
に設定します。
import axios from 'axios';
axios.interceptors.response.use(
(response) => {
if (response.config.url === 'https://jsonplaceholder.typicode.com/todos/1') {
return response.data as Todo; // Todo 型にキャスト
}
return response;
},
(error) => {
return Promise.reject(error);
}
);
カスタム型ガード
カスタム型ガードを使用して、API レスポンスの型を検証することができます。
function isTodo(data: any): data is Todo {
return typeof data === 'object' && 'id' in data && 'userId' in data && 'title' in data && 'completed' in data;
}
const fetchData = async () => {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1');
const data = response.data;
if (isTodo(data)) {
console.log(data);
} else {
console.error('Invalid data format');
}
} catch (error) {
console.error(error);
}
};
fetchData();
このコードは、isTodo
関数を使用して、API レスポンスの型を検証します。isTodo
関数が true
を返した場合、データは Todo
型であることが保証されるため、安全に操作することができます。
GraphQL
GraphQL を使用して API を呼び出すと、API レスポンスの構造を事前に定義することができます。
import { useQuery } from '@apollo/client';
const GET_TODO = gql`
query GetTodo($id: ID!) {
todo(id: $id) {
id
userId
title
completed
}
}
`;
const App: React.FC = () => {
const { data, loading, error } = useQuery(GET_TODO, { variables: { id: 1 } });
if (loading) {
return <div>Loading...</div>;
}
if (error) {
return <div>{error.message}</div>;
}
const todo = data?.todo;
if (!todo) {
return <div>Todo not found</div>;
}
return (
<div>
<h1>{todo.title}</h1>
<p>Completed: {todo.completed ? 'Yes' : 'No'}</p>
</div>
);
};
export default App;
このコードは、GraphQL クエリを使用して https://jsonplaceholder.typicode.com/todos/1
エンドポイントにクエリを実行し、レスポンスを Todo
型に自動的にマッピングします。
JSON Schema
JSON Schema を使用して API レスポンスの構造を事前に定義することができます。
import Ajv from 'ajv';
const ajv = new Ajv();
const todoSchema = {
type: 'object',
properties: {
reactjs typescript axios