React で関数コンポーネントをモジュール化する際の記述方法とフォルダ構成について詳しく説明します。モジュール化することで、コードの再利用性が高まり、プロジェクトの規模が大きくなっても管理しやすくなります。
1. フォルダ構成の提案
以下は、React プロジェクトで一般的に使用されるフォルダ構成の一例です。各コンポーネントを独立したフォルダに分け、関連するファイルをまとめることで、可読性と保守性を向上させます。
src/
├── components/
│ ├── Button/
│ │ ├── Button.jsx
│ │ ├── Button.module.css
│ │ └── index.js
│ ├── Header/
│ │ ├── Header.jsx
│ │ ├── Header.module.css
│ │ └── index.js
│ └── ... 他のコンポーネント
├── pages/
│ ├── Home/
│ │ ├── Home.jsx
│ │ ├── Home.module.css
│ │ └── index.js
│ └── ... 他のページ
├── App.jsx
├── index.js
└── ... その他のファイル
フォルダ構成のポイント
- components/: 再利用可能な UI コンポーネントを格納します。各コンポーネントは独自のフォルダを持ち、その中に
jsx
ファイル、スタイルシート、テストファイルなどを配置します。 - pages/: アプリケーションの各ページを格納します。ページもコンポーネントとして扱い、同様に独自のフォルダを持ちます。
- index.js: 各コンポーネントフォルダ内の
index.js
を使用して、コンポーネントのデフォルトエクスポートをまとめて管理します。
2. 関数コンポーネントのモジュール化
例: Button コンポーネント
フォルダ構成
components/
└── Button/
├── Button.jsx
├── Button.module.css
└── index.js
Button.jsx
// src/components/Button/Button.jsx
import React from 'react';
import styles from './Button.module.css';
import PropTypes from 'prop-types';
const Button = ({ onClick, children, type = 'button' }) => {
return (
<button type={type} className={styles.button} onClick={onClick}>
{children}
</button>
);
};
Button.propTypes = {
onClick: PropTypes.func,
children: PropTypes.node.isRequired,
type: PropTypes.string,
};
export default Button;
Button.module.css
/* src/components/Button/Button.module.css */
.button {
padding: 10px 20px;
background-color: #007bff;
border: none;
color: white;
border-radius: 4px;
cursor: pointer;
}
.button:hover {
background-color: #0056b3;
}
index.js
// src/components/Button/index.js
export { default } from './Button';
使用方法
他のコンポーネントやページから Button
コンポーネントを使用する際は、以下のようにインポートします。
// 例: src/pages/Home/Home.jsx
import React from 'react';
import Button from '../../components/Button';
const Home = () => {
const handleClick = () => {
alert('Button clicked!');
};
return (
<div>
<h1>ホームページ</h1>
<Button onClick={handleClick}>クリックしてください</Button>
</div>
);
};
export default Home;
3. 他のコンポーネントの例
Header コンポーネント
フォルダ構成
components/
└── Header/
├── Header.jsx
├── Header.module.css
└── index.js
Header.jsx
// src/components/Header/Header.jsx
import React from 'react';
import styles from './Header.module.css';
import PropTypes from 'prop-types';
const Header = ({ title }) => {
return (
<header className={styles.header}>
<h1>{title}</h1>
</header>
);
};
Header.propTypes = {
title: PropTypes.string.isRequired,
};
export default Header;
Header.module.css
/* src/components/Header/Header.module.css */
.header {
background-color: #f8f9fa;
padding: 20px;
text-align: center;
border-bottom: 1px solid #dee2e6;
}
.header h1 {
margin: 0;
font-size: 24px;
color: #343a40;
}
index.js
// src/components/Header/index.js
export { default } from './Header';
使用方法
// 例: src/pages/Home/Home.jsx
import React from 'react';
import Header from '../../components/Header';
import Button from '../../components/Button';
const Home = () => {
const handleClick = () => {
alert('Button clicked!');
};
return (
<div>
<Header title="ホームページ" />
<Button onClick={handleClick}>クリックしてください</Button>
</div>
);
};
export default Home;
4. 全体の App.jsx と index.js
App.jsx
// src/App.jsx
import React from 'react';
import Home from './pages/Home';
const App = () => {
return (
<div>
<Home />
</div>
);
};
export default App;
index.js
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css'; // グローバルスタイル
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
5. 追加のベストプラクティス
- スタイル管理: 各コンポーネントに専用の CSS モジュール (
.module.css
) を使用することで、スタイルのスコープをコンポーネントに限定し、クラス名の競合を防ぎます。 - PropTypes の使用:
prop-types
パッケージを使用して、コンポーネントのプロパティの型を定義し、開発時のバグを防ぎます。 - インデックスファイルの活用: 各コンポーネントフォルダ内の
index.js
を使用してデフォルトエクスポートを再エクスポートすることで、インポート時のパスを簡略化できます。
// src/components/Button/index.js
export { default } from './Button';
// インポート時
import Button from 'components/Button';
- テストの追加: 各コンポーネントに対応するテストファイル (
Button.test.jsx
など) を追加することで、コンポーネントの動作を自動で検証できます。
まとめ
React の関数コンポーネントをモジュール化する際は、各コンポーネントを独立したフォルダに分け、関連ファイルをまとめることで、コードの可読性と保守性を向上させることができます。以下のポイントを押さえて、効率的なプロジェクト構成を実現しましょう。
- コンポーネントごとにフォルダを作成
- スタイルシートやテストファイルを同じフォルダに配置
index.js
を活用してインポートを簡略化- PropTypes でプロパティの型を定義
これらのベストプラクティスを採用することで、大規模なアプリケーションでも効率的に開発を進めることができます。