【React】入門してみたまとめ ✍🏻

# Reactとは

> React はユーザインターフェイスを構築するための、宣言型で効率的で柔軟な JavaScript ライブラリです。複雑な UI を、「コンポーネント」と呼ばれる小さく独立した部品から組み立てることができます。


## Reactの導入

React環境を構築するのはとても大変でWebpack や Babel もしくは TypeScript などの知識に精通している必要がある。
今回はCreate React Appという、ツールを使用してReactを導入してみる🛠
Create React Appは簡単に言うとReactの開発環境の雛形で難しい設定をしなくても簡単にReactを導入できるツール。

ターミナルで下記コマンドを実施。グローバル`-g`でcreate-react-appをインストール
`sudo npm i -g create-react-app`

 create-react-app {フォルダ名} でプロジェクトの作成
`create-react-app sample-react`

ディレクトリ移動してサーバー立ち上げ。ctrl + cでサーバー停止
`cd sample-react`
`npm start`

## コマンド確認

creat-react-appによって生成されたpackage.jsonで使用できるコマンドを確認してみる。
```package.json
"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
```
*  start・・・開発用サーバーの立ち上げ。基本的にこのコマンドで開発を行なっていく。
*  build・・・本番環境アップ用のスクリプトを生成。
*  test・・・テストスクリプト。テストコードを流すためのコマンド
*  eject・・・隠し設定の可視化をするコマンド。こちらのコマンドを叩くと、隠されていたconfigディレクトリなどの設定ファイルが表示される。

## styleの当て方

JSXにclassName属性を記述し、cssファイルをimport、スタイリング。

```jsx
import "./Example.css"; // cssファイルimport
const Example = () => {
  return (
    <div className="component"> // className属性付与
      <h3>Hello Component</h3>
    </div>
  );
};

export default Example;
```

```Example.css
.component {
  background: red;
}
```

## コンポーネントの定義と分割方法

コンポーネントとはReactで画面に表示される部品のことで、表示に必要なデータや処理などを1つのオブジェクトにまとめたもの。
これらのコンポーネントを用いて構築していくことで、再利・可読性の向上、疎結合によるバグ発生率の低下が期待できる。

### コンポーネントの定義

コンポーネントはJavaScriptの関数として定義する。
この関数コンポーネントは表示するエレメントをJSXで記述し、returnで返すことが基本となる。
関数名の先頭は大文字にすることでコンポーネントであることを明示的に示す。

関数コンポーネントの定義
```jsx
function Sample() {
  return <h1>Hello</h1>;
}
```

コンポーネントの実行
```jsx
<Sample>
```

アロー関数でも可能
```jsx
const Sample = () => {
  return <h1>Hello</h1>;
}

// 省略
const Sample = () => <h1>Hello</h1>;
```

returnするJSXのコードが複数行の場合は`()`で囲む必要がある。
```jsx
function Sample() {
  return (
    <div>
      <h1>Hello</h1>
    </div>
  );
}

// アロー関数
const Sample = () => (
  <div>
    <h1>Hello</h1>
  </div>
);
```

### 分割方法

関数コンポーネント定義し、それを`export`。
その関数コンポーネントを呼び出したいファイルで`import`し実行。

関数コンポーネント
```jsx
const List = () => {
  return (
    <ul>
      <li>item-1</li>
      <li>item-2</li>
      <li>item-3</li>
      <li>item-4</li>
      <li>item-5</li>
    </ul>
  );
};

export { List }; // 名前付きexport
// defaultexportする場合は下記
// export default List;
```

```jsx
import { List } from "./components/List"; // 関数コンポーネントimport
// defaultexportをimportする場合は下記
// import  List from "./components/List";

const Example = () => {
  return (
    <div className="component">
      <h3>Hello Component</h3>
      <List />
    </div>
  );
};

export default Example;
```
![スクリーンショット 2022-12-23 15.24.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/473680b8-a0f6-120a-83e7-d1a130354ada.png)

1コンポーネントファイルには基本的に1コンポーネントを記述する形だと思うので、その場合、わざわざ名前付きexportする必要はなく基本的に`default export`の書き方でよさそう。

## React Fragmentの使い方

フラグメントとは

> React でよくあるパターンの 1 つに、コンポーネントが複数の要素を返すというものがあります。フラグメント (fragment) を使うことで、DOM に余分なノードを追加することなく子要素をまとめることができるようになります。

[React公式](https://ja.reactjs.org/docs/fragments.html#gatsby-focus-wrapper)

Reactコンポーネントはルートの要素がひとつでないといけないという制限がある。

ルート要素が一つ
```jsx
const Sample = () => {
  return (
    <div className="component">
      <h3>Hello Component</h3>
      <h3>Hello Fragment</h3>
      <p>サンプルテキストサンプルテキストサンプルテキストサンプルテキストサンプルテキスト</p>
    </div>
  );
};
```

ルート要素が三つだとエラー
```jsx
const Sample = () => {
  return (
    <div className="component">
      <h3>Hello Component</h3>
    </div>
    <h3>Hello Fragment</h3>
    <p>サンプルテキストサンプルテキストサンプルテキストサンプルテキストサンプルテキスト</p>
  );
};
```
![スクリーンショット 2022-12-23 18.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/d723234e-fe1d-166f-6d36-317404735bd8.png)

このようにルート要素を一つにする必要があるが、ルート要素を一つにするためだけの要素を作成したくない場合などにReactフラグメントを使用する。


```jsx
import React from "react"; // reactパッケージのdefaultインポート
const Sample = () => {
  return (
     <React.Fragment>
      <div className="component">
        <h3>Hello Component</h3>
      </div>
      <h3>Hello Fragment</h3>
      <p>サンプルテキストサンプルテキストサンプルテキストサンプルテキストサンプルテキスト</p>
    </React.Fragment>
  );
};
```

実際に生成されるElementsは`React.Fragment`部分は何も出力されない。
ショートハンドとして`<>`だけでも可。
このショートハンドを使用するならReactのimportは必要ない。
ちなみにReactNativeだとこのショートハンドは使えないらしい。

フラグメントには`key`という属性のみ付与できる。

## JSX内でJavaScriptのコードを実行する方法

jsxのコード内では`{}`を使ってjsの**式**を評価してその結果を出力する。
なのでfor文やif文などの文はreturnするjsxの`{}`内では使えない。

:::note warn
**式とは**
何らかの値を返すもの(変数に代入できるもの)

**文とは**
変数宣言、for文、if文、switch文やセミコロンで区切るもの
:::

例
```jsx
import "./Sample.css";

const Expression = () => {
  const title = "SampleTitle";
  const arry = ["item1", "item2", "item3"];
  const hello = (arg) => `${arg} Function`;
  const jsx = <h3>こんにちは！ JSX</h3>;
  return (
    <div className={title.toLowerCase()}>
      <h3>Hello {title}!</h3>
      <h3>{arry}</h3>
      <h3>{hello("Hello")}</h3>
      {/**コメント */}
      {<h3>Hello JSX</h3>}
      {jsx}
    </div>
  );
};
export default Expression;
```
```Sample.css
.sampletitle {
  color: red;
}
```
![スクリーンショット 2022-12-24 12.22.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/10ffead5-3d69-09b3-0f69-5b7ef9602c96.png)

:::note warn
toLowerCase()は文字列全て小文字に変換するメソッド。
配列を渡した場合、自動的に展開され結合したものを出力する。
:::

## propsでコンポーネントに値を渡す

関数コンポーネントに仮引数をとり、実行時に属性を記述することで、その属性が実引数として渡ってくる。

```jsx
import Child from "./components/Child";

const Example = () => <Child color="red" />;

export default Example;
```

```jsx
const Child = (props) => {
  console.log(props); // → {color: 'red'}
  console.log(props.color); // → red
  return (
    <div className="component">
      <h3>Hello Component</h3>
    </div>
  );
};

export default Child;
```

このpropsをclassNameに利用して再利用性の高いコンポーネントなどを作成できる。

```jsx
const Child = (props) => {
  return (
    <div className={`component ${props.color}`}>
      <h3>Hello Component</h3>
    </div>
  );
};

export default Child;
```
上記コンポーネントを`<Child color="red" />`で実行するとclassが`component red`になるので下記のようにスタイリングできる。

```css
.component.red {
  color: red;
  border: 5px solid red;
}

/* <Child />のように属性を取らなければこちらのスタイルが当たる */
.component {
  color: blue;
  border: 5px solid blue;
}
```

:::note warn
分割代入でも可！

例)
```jsx
const Child = ({color}) => {
  return (
    <div className={`component ${color}`}>
      <h3>Hello Component</h3>
    </div>
  );
};
```
:::

:::note warn
デフォルト引数を使用して引数が渡ってこなかった場合の設定も可！

例)
```jsx
const Child = ({color = "green"}) => {
  return (
    <div className={`component ${color}`}>
      <h3>Hello Component</h3>
    </div>
  );
};
```
:::

### propsで色んな値を渡してみる

例)num属性を追加して、表示
```jsx
import Child from "./components/Child";

const Example = () => <Child color="red" num={123} />;

export default Example;
```

```jsx
import "./Child.css";

const Child = (props) => {
  return (
    <div className={`component ${props.color}`}>
      <h3>Hello Component</h3>
      <p>{props.num}</p>
    </div>
  );
};

export default Child;
```

___

例)関数helloをfn属性として追加、表示
```jsx
import Child from "./components/Child";

const Example = () => {
  const hello = (arg) => `Hello ${arg}`;
  return (
    <>
      <Child
        color="red"
        num={123}
        fn={hello}
      />
    </>
  );
};

export default Example;
```

```jsx
import "./Child.css";

const Child = ({ color, num, fn }) => { // 分割代入に変更
  return (
    <div className={`component ${color}`}>
      <h3>Hello Component</h3>
      <p>{num}</p>
      <p>{fn("React")}</p>
    </div>
  );
};

export default Child;
```

___

例)bool属性としてBooleanを追加。属性を追加するだけで`true`になり、追加されていない場合は`false`になる
```jsx
import Child from "./components/Child";

const Example = () => {
  const hello = (arg) => `Hello ${arg}`;
  return (
    <>
      <Child
        color="red"
        num={123}
        fn={hello}
        bool
      />
    </>
  );
};

export default Example;
```

```jsx
import "./Child.css";

const Child = ({ color, num, fn, bool }) => {
  return (
    <div className={`component ${color}`}>
      <h3>Hello Component</h3>
      <p>{num}</p>
      <p>{fn("React")}</p>
      <p>{bool ? "true" : "false"}</p>
    </div>
  );
};

export default Child;
```

___

例)obj属性としてオブジェクトを追加

```jsx
import Child from "./components/Child";

const Example = () => {
  const hello = (arg) => `Hello ${arg}`;
  return (
    <>
      <Child
        color="red"
        num={123}
        fn={hello}
        bool
        obj={{
          name: "Sato",
          age: "26",
        }}
      />
    </>
  );
};

export default Example;
```

```jsx
import "./Child.css";

const Child = ({ color, num, fn, bool, obj }) => {
  return (
    <div className={`component ${color}`}>
      <h3>Hello Component</h3>
      <p>{num}</p>
      <p>{fn("React")}</p>
      <p>{bool ? "true" : "false"}</p>
      <p>{`name:${obj.name} age:${obj.age}`}</p>
    </div>
  );
};

export default Child;
```

上記コードのレンダリング結果
![スクリーンショット 2023-01-03 18.05.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/98d7ee4f-e143-a50f-75c9-10fd049c6962.png)

## `children`という特別なpropsについて

関数コンポーネントに閉じタグを追加することで、コンポーネントタグで囲まれた中に記述された内容が`children`となり、コンポーネント内でその内容を`children`として扱うことができる。

例)コンポーネントタグ内に`テスト`という値を記述
```jsx
const Example = () => {
  return (
    <div>
      <Container title="Childrenとは？">テスト</Container>
    </div>
  );
};

export default Example;
```

コンポーネントタグ内の値は`children`propsとして扱える
```jsx
const Container = ({ title, children }) => { // 分割代入(childrenは固定名詞)
  return (
    <div className="container">
      <h3>{title}</h3>
      <p>{children}</p>
    </div>
  );
};

export default Container;
```
![スクリーンショット 2023-01-03 18.54.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/08307682-6054-7c2f-d382-96bae7d9a5f3.png)

コンポーネントのネストなどの使い方ができる
```jsx
const Example = () => {
  return (
    <div>
      <Container title="Childrenとは？">
        <SampleComponent />
      </Container>
    </div>
  );
};

export default Example;
```

`{children}`で`<SampleComponent />`コンポーネントが実行される。
```jsx
const Container = ({ title, children }) => {
  return (
    <div className="container">
      <h3>{title}</h3>
      {children}
    </div>
  );
};

export default Container;
```

## JSXとは

ReactによるJavaScriptの構文を拡張したもの。
JSXはJSのオブジェクトに変換される。
「JSX」とは、「JavaScript XML」の略であり、Reactのコンポーネント内でマークアップ言語を記述するためのXML風の構文で、以下のようなもの。

```jsx
function render(){
  return (
    <ul>
      <li>togamin.com</li>
      <li>fresopiya.com</li>
    </ul>
  );
}
```

JSX構文を利用しない場合は、上記のコードは以下のようになる。

```js
function render(){
  return React.createElement( 
    'ul',
    null,
    React.createElement('li', null, 'togamin.com'),
    React.createElement('li', null, 'fresopiya.com')
  );
}
```

## 参考

https://www.udemy.com/course/react-complete-guide/