React プロジェクトにおける各フォルダ(components、hooks、services、store、utils)の用途について詳しく説明します。これらのフォルダは、プロジェクトの構造を整理し、コードの可読性や保守性を向上させるために重要な役割を果たします。
1. components フォルダ
用途
components
フォルダは、再利用可能な UI コンポーネントを格納するための場所です。これらのコンポーネントは、アプリケーションの様々な部分で使用され、UI の一貫性を保つ役割を担います。
内容
- プレゼンテーショナルコンポーネント: 状態を持たず、受け取ったプロパティに基づいて表示を行うコンポーネント。
- コンテナコンポーネント: 状態管理やロジックを担当し、プレゼンテーショナルコンポーネントにデータを渡すコンポーネント。
例
src/
├── components/
│ ├── Button/
│ │ ├── Button.jsx
│ │ ├── Button.test.js
│ │ └── Button.module.css
│ └── Header/
│ ├── Header.jsx
│ ├── Header.test.js
│ └── Header.module.css
Button.jsx
import React from 'react';
import styles from './Button.module.css';
const Button = ({ onClick, children }) => {
return (
<button className={styles.button} onClick={onClick}>
{children}
</button>
);
};
export default Button;
2. hooks フォルダ
用途
hooks
フォルダには、カスタム React フックを格納します。カスタムフックは、再利用可能なロジックを抽象化し、複数のコンポーネント間で共有するために使用されます。
内容
- カスタムフック: 特定の機能やロジックを実装したフック(例: データフェッチング、フォーム処理、認証など)。
例
src/
├── hooks/
│ └── useAuth.js
useAuth.js
import { useState, useEffect } from 'react';
import { authService } from '../services/authService';
const useAuth = () => {
const [user, setUser] = useState(null);
useEffect(() => {
authService.getCurrentUser().then(setUser);
}, []);
const login = async (credentials) => {
const loggedInUser = await authService.login(credentials);
setUser(loggedInUser);
};
const logout = () => {
authService.logout();
setUser(null);
};
return { user, login, logout };
};
export default useAuth;
3. services フォルダ
用途
services
フォルダには、API 呼び出しや外部サービスとの通信を担当するロジックを格納します。これにより、ビジネスロジックと UI ロジックを分離し、コードの再利用性とテストのしやすさを向上させます。
内容
- API クライアント: REST API や GraphQL エンドポイントとの通信を行う関数やクラス。
- 認証サービス: ログイン、ログアウト、ユーザー情報の取得などの認証関連のロジック。
例
src/
├── services/
│ └── api.js
api.js
import axios from 'axios';
const apiClient = axios.create({
baseURL: 'https://api.example.com',
headers: {
'Content-Type': 'application/json',
},
});
export const getPosts = () => apiClient.get('/posts');
export const getPostById = (id) => apiClient.get(`/posts/${id}`);
export const createPost = (postData) => apiClient.post('/posts', postData);
// 他のAPI呼び出しもここに追加
4. store フォルダ
用途
store
フォルダは、アプリケーションのグローバルな状態管理を担当します。Redux や Context API などの状態管理ライブラリを使用する場合、このフォルダに関連するファイルを配置します。
内容
- アクション(actions): 状態を変更するためのイベントやデータ。
- リデューサー(reducers): アクションに応じて状態を更新する関数。
- ストア(store): アプリケーション全体の状態を保持する場所。
例
src/
├── store/
│ ├── actions/
│ │ └── authActions.js
│ ├── reducers/
│ │ └── authReducer.js
│ └── store.js
store.js
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import authReducer from './reducers/authReducer';
const rootReducer = combineReducers({
auth: authReducer,
// 他のリデューサーをここに追加
});
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
authActions.js
import { LOGIN_SUCCESS, LOGOUT } from '../types';
import { authService } from '../../services/authService';
export const login = (credentials) => async (dispatch) => {
const user = await authService.login(credentials);
dispatch({ type: LOGIN_SUCCESS, payload: user });
};
export const logout = () => (dispatch) => {
authService.logout();
dispatch({ type: LOGOUT });
};
authReducer.js
import { LOGIN_SUCCESS, LOGOUT } from '../types';
const initialState = {
user: null,
};
const authReducer = (state = initialState, action) => {
switch (action.type) {
case LOGIN_SUCCESS:
return { ...state, user: action.payload };
case LOGOUT:
return { ...state, user: null };
default:
return state;
}
};
export default authReducer;
5. utils フォルダ
用途
utils
フォルダには、アプリケーション全体で再利用可能なユーティリティ関数やヘルパー関数を格納します。これらの関数は、特定のビジネスロジックに依存せず、汎用的に使用できるものです。
内容
- フォーマット関数: 日付や数値のフォーマット。
- バリデーション関数: 入力値の検証。
- その他のヘルパー関数: データ変換、計算処理など。
例
src/
├── utils/
│ └── formatDate.js
formatDate.js
export const formatDate = (date, locale = 'en-US') => {
return new Date(date).toLocaleDateString(locale, {
year: 'numeric',
month: 'long',
day: 'numeric',
});
};
// 他のユーティリティ関数もここに追加
まとめ
各フォルダの役割を明確に分けることで、React プロジェクトの構造が整理され、以下のようなメリットが得られます。
- 可読性の向上: 新しい開発者がプロジェクトに参加しやすくなります。
- 保守性の向上: バグ修正や機能追加が容易になります。
- 再利用性の向上: コンポーネントや関数を他の部分でも簡単に再利用できます。
- スケーラビリティ: プロジェクトが大規模になっても対応しやすくなります。
これらのフォルダ構成を適切に採用することで、効率的かつ効果的な開発が可能となります。プロジェクトのニーズに合わせて柔軟に構造を調整し、最適な開発環境を整えてください。