React コンポーネントのインポート/エクスポート

# 成果物
今回作成したのはCounterコンポーネントとNameコンポーネントを合わせたものになります。

CounterコンポーネントとNameコンポーネントのように、それぞれ機能単位でコンポーネントにまとめながらアプリケーションを開発することを`コンポーネント指向`といいます。
CounterコンポーネントとNameコンポーネントをそれぞれ別のファイルに記述しエクスポートしてまとめます。

https://codesandbox.io/embed/konponentozhi-xiang-arenzi-51tbcr?fontsize=14&hidenavigation=1&theme=dark

# コード
## index.js
```javascript
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
```

## App.js
```javascript
import React, { useState } from "react";
import "./styles.css";

// CounterコンポーネントとNameコンポーエントをインポートする
import { Counter } from "./Counter";
import { Name } from "./Name";

// 初期値を設定
const INITIAL_COUNT = 0;
const INITIAL_NAME = "";

export default function App() {

  // カウントAの現在の状態変数countA、カウントAの状態を更新する関数setCountAを定義
  const [countA, setCountA] = useState(INITIAL_COUNT);
  
  // カウントBの現在の状態変数countB、カウントBの状態を更新する関数setCountBを定義
  const [countB, setCountB] = useState(INITIAL_COUNT);
  
  // カウントAとカウントBの合計値であるカウントABの現在の状態変数countABを定義
  // カウントABの状態を更新する関数setCountABを設定
  const [countAB, setCountAB] = useState(INITIAL_COUNT);

  // 姓の現在の状態変数firstName、姓の状態を更新する関数setFisrtNameを定義
  const [firstName, setFirstName] = useState(INITIAL_NAME);

  // 名の現在の状態変数lastName、名の状態を更新する関数setLastNameを定義
  const [lastName, setLastName] = useState(INITIAL_NAME);

  // 1ずつカウントアップする関数countAIncrementを定義
  const countAIncrement = () => setCountA((prevCount) => prevCount + 1);
  
  // 1ずつカウントダウンする関数countAIncrementを定義
  const countADecrement = () => setCountA((prevCount) => prevCount - 1);

  // 1ずつカウントアップする関数countBIncrementを定義
  const countBIncrement = () => setCountB((prevCount) => prevCount + 1);

  // 1ずつカウントダウンする関数countBIncrementを定義
  const countBDecrement = () => setCountB((prevCount) => prevCount - 1);

  // 設定された値をリセットする関数countResetを定義
  // カウントA、カウントB、カウントAB(カウントAとカウントBの合計値)をリセットする
  const countReset = () => {
    setCountA(INITIAL_COUNT);
    setCountB(INITIAL_COUNT);
    setCountAB(INITIAL_COUNT);
  };

  // カウントAとカウントBを合計する関数countSumを定義
  const countSum = () => {
    setCountAB(countA + countB);
  };

  // フォームに入力された値（姓）を設定する関数setFirstNameを定義
  const handleFirstName = (e) => setFirstName(e.target.value);

  // フォームに入力された値（名）を設定する関数setFirstNameを定義
  const handleLastName = (e) => setLastName(e.target.value);

  // 状態変数firstName、lastNameに設定された値をリセットする関数nameResetを定義
  const nameReset = () => {
    setFirstName(INITIAL_NAME);
    setLastName(INITIAL_NAME);
  };

  return (
    <>
      // Counterコンポーエントに以下の値、関数を渡す
      <Counter
        countA={countA}
        countB={countB}
        countAB={countAB}
        countAIncrement={countAIncrement}
        countADecrement={countADecrement}
        countBIncrement={countBIncrement}
        countBDecrement={countBDecrement}
        countReset={countReset}
        countSum={countSum}
      />
      <hr />
      // Nameコンポーネントに以下の値、関数を渡す
      <Name
        firstName={firstName}
        lastName={lastName}
        handleFirstName={handleFirstName}
        handleLastName={handleLastName}
        nameReset={nameReset}
      />
    </>
  );
}
```

## Counter.js
```javascript
// 他のファイルでもCounterコンポーネントを利用できるようexportする
// 親コンポーネントであるAppから渡されたpropsを受け取る
export const Counter = (props) => {
  return (
    <>
      <h1>Counterコンポーネント</h1>
      <p>
        A+B= <b>{props.countAB}</b>
      </p>
      <div>
        <p>
          現在のカウントA:<b>{props.countA}</b>
        </p>

        // ボタンが押された際にカウントAを+1する
        <button onClick={props.countAIncrement}>カウントA: +1</button>

        // ボタンが押された際にカウントAを-1する
        <button onClick={props.countADecrement}>カウントA: -1</button>
      </div>
      <div>
        <p>
          現在のカウントB:<b>{props.countB}</b>
        </p>

        // ボタンが押された際にカウントBを+1する
        <button onClick={props.countBIncrement}>カウントB: +1</button>

        // ボタンが押された際にカウントBを-1する
        <button onClick={props.countBDecrement}>カウントB: -1</button>
      </div>
      <br />

      // ボタンが押された際にカウントAとカウントBの値を合計する
      <button onClick={props.countSum}>合計</button>

      // ボタンが押された際にカウントA、カウントB、カウントAB(カウントAとカウントBの合計値)をリセットする
      <button onClick={props.countReset}>リセット</button>
    </>
  );
};

```

## Name.js
```javascript
// 他のファイルでもNameコンポーネントを利用できるようexportする
// 親コンポーネントであるAppから渡されたpropsを受け取る
export const Name = (props) => {
  return (
    <>
      <h1>Nameコンポーネント</h1>
      <p>
        私の名前は
        <b>
          {props.firstName} {props.lastName}
        </b>
        です
      </p>
      <div>
        <label>姓：</label>
        <input
          type="text"
          value={props.firstName}

          // フォームに値が入力された、または削除された際に関数handleFirstNameを実行
          onChange={props.handleFirstName}
        />
      </div>
      <div>
        <label>名：</label>
        <input
          type="text"
          value={props.lastName}

          // フォームに値が入力された、または削除された際に関数handleLastNameを実行
          onChange={props.handleLastName}
        />
      </div>
      <br />

      // フォーム（姓、名）に入力された値と表示しているフルネームを削除する
      <button onClick={props.nameReset}>リセット</button>
    </>
  );
};
```

## styles.css
今回は記述なし

# エクスポートとインポートの別の方法
## 今回の方法
今回は以下のようにエクスポートとインポートを行いました。
CounterコンポーネントとNameコンポーネントをそれぞれexportし、それぞれをAppコンポーネントでimportしました。
```javascript:App.js
// 親コンポーネント
import { Counter } from "./Counter";
import { Name } from "./Name";

export default function App() {
// 省略
};
```

```javascript:Counter.js
// 子コンポーネント
export const Counter = (props) => {
// 省略
};
```

```javascript:Name.js
// 子コンポーネント
export const Name = (props) => {
// 省略
};
```

## 別の方法
インポート、エクスポートは以下のような方法でも可能です。
ポイントは2点あります。
- [ ] ファイルの最後に`export default コンポーネント名`と記述する
- [ ] exportしたコンポーネントを`import コンポーネント名 from 相対パス`（コンポーネント名には`{}`をつけない）
```javascript:App.js
// 親コンポーネント
import Counter from "./Counter";
import Name from "./Name";

function App() {
// 省略
};

export default App;
```

```javascript:Counter.js
// 子コンポーネント
const Counter = (props) => {
// 省略
};

export default Counter;
```

```javascript:Name.js
// 子コンポーネント
const Name = (props) => {
// 省略
};

export default Name;
```