【初心者】React記述メモ【備忘録】

# はじめに
投稿時点で、筆者は知識ゼロの状態から勉強を初めて2ヶ月程度の実力です。
そのため、理解不足や説明不足、誤った内容や呼び方をしている可能性があります。
万が一参考にする場合は上記の点を考慮した上でご一読ください。
説明文の内容はChatGPT先生からの引用が多いです。

# コンポーネント記述方法
下記は全て同じ役割になる。
```javascript
// Class Component（クラスコンポーネント）
class App extends React.Component {
  render() {
    return(
			<div>
				<h1>Hello World</h1>
			</div>
    );
  };
};
```
```javascript
// Functional Component（関数コンポーネント）（ES5で書いた場合）
function App(props) {
  return(
    <div>
      <h1>Hello World</h1>
    </div>
  );
};
```

```javascript
// Functional Component（関数コンポーネント）（ES6（アロー関数）で書いた場合）
const App = (props) => {
  return(
		<div>
			<h1>Hello World</h1>
		</div>
  );
};
```

```javascript
// Functional Component（関数コンポーネント）（ES6（アロー関数）で書いた場合）
// 以下のように無駄な部分を削ぎ落として超シンプルに書くことも可能
const App = props => <div><h1>Hello World</h1></div>;
```

## return文について
1行だけなら`return()`は無しでもOK。
改行して記述したい場合は（）で範囲を指定しないとエラーが出る。

## Fragmentについて
Reactでは、コンポーネント内で`<div>`を使用することが多いですが、`<React.Fragment>`を使用することで、不必要な`<div>`要素を回避することができます。
```javascript:①
const App = (props) => {
  return(
		<div>
			<h1>Hello World</h1>
		</div>
  );
};
```
```html:①の出力結果
<div>
  <h1>Hello World</h1>
</div>
```


```javascript:②
const App = (props) => {
  return(
		<React.Fragment>
			<h1>Hello World</h1>
		</React.Fragment>
  );
};
```
```html:②の出力結果
<h1>Hello World</h1>
```
```javascript:③　<>だけでも同じことが可能
const App = (props) => {
  return(
		<>
			<h1>Hello World</h1>
		</>
  );
};
```
```html:③の出力結果
<h1>Hello World</h1>
```

## propsについて。
propsはコンポーネントの引数のこと
親コンポーネント側で`<子コンポーネント プロパティ名={値} />`として渡し、子コンポーネント側で`{props.プロパティ名}`として受け取ることができます。
関数コンポーネントやクラスコンポーネントに関わらず、設定されているpropsは絶対に変更してはいけません。
propsは読み取り専用のものだと覚えておきましょう。
propsはコンポーネント間で受け渡しする際に必要で、stateはコンポーネント内でデータの受け渡しをする際に必要、と覚えると楽かも。

## stateについて
Stateとは、ユーザーの動きに合わせて変わる値のこと、ReactではStateと呼びます
```javascript:
// Class Component（クラスコンポーネント）
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name:'〇〇'}; //オブジェクトとして定義したものをthis.stateに代入
  };
  render() {
	console.log(this.state);  // {name:'○○'}というオブジェクトが表示される
    console.log(this.state.name);  // ○○が表示される(this.stateプロパティ名)
    return(
			// 省略
    );
  };
};
```
↑メモ：関数コンポーネントの記述に変更すること（気力あったら…）


# 親子コンポーネントの記述
## 通常の記述
```html:index.html
<div id="root"></div>
```
```javascript:index.jsx
// 最上位？（呼び名わからん）コンポーネント（index.jsx）
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";

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

root.render(
  <Parent />
);

```

```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/Child';

const Parent = () => {
  return(
		<div>
			<Child
			title = {'Hello World'}
			/>
		</div>
  );
};

export default Parent;
```

```javascript:child.jsx
// 子コンポーネント（components/child.jsx）
import React from "react";

const Child = (props) => {
  return(
		<div>
			<h1>{props.title}</h1>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello World
```

## 分割代入で記述
もっと簡潔に記述するには分割代入をします。
{}の中に引数名を記述することで、渡された引数を受け取ることができます。
```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/Child';

const Parent = () => {
  return(
		<div>
			<Child
			title = {'Hello World'}
			/>
		</div>
  );
};

export default Parent;
```
```javascript:child.jsx
// 子コンポーネント（components/child.js）
import React from "react";

const Child = ({title}) => {
  return(
		<div>
			<h1>{title}</h1>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello World
```

## 複数の引数を分割代入で記述

```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/Child';

const Parent = () => {
  return(
		<div>
			<Child
			title = {'Hello'}
			text = {'World'}
			message = {'thanks'}
			/>
		</div>
  );
};

export default Parent;
```
```javascript:child.jsx
// 子コンポーネント（components/child.js）
import React from "react";

const Child = ({title, text, message}) => {
  return(
		<div>
			<h1>{title}</h1>
			<p>{text}</p>
			<p>{message}</p>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello
World
thanks
```
## 子コンポーネントで初期値を指定する方法

親コンポーネントで引数を省略することができ、指定しなければこちらの初期値が優先されます。

### 例1
```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/Child';

const Parent = () => {
  return(
		<div>
			<Child
			/>
		</div>
  );
};

export default Parent;
```
```javascript:child.jsx
// 子コンポーネント（components/child.js）
import React from "react";

const Child = ({title = 'Hello', text = 'World', message = 'thanks'}) => {
  return(
		<div>
			<h1>{title}</h1>
			<p>{text}</p>
			<p>{message}</p>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello
World
thanks
```



### 例2
```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/child';

const Parent = () => {
  return(
		<div>
			<Child
			title = {'Hello'}
			text = {'World'}
			/>
		</div>
  );
};

export default Parent;
```

```javascript:child.jsx
// 子コンポーネント（components/child.js）
import React from "react";

const Child = ({title, text, message = 'thanks'}) => {
  return(
		<div>
			<h1>{title}</h1>
			<p>{text}</p>
			<p>{message}</p>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello
World
thanks
```

親コンポーネント側でmessage内のpropsを子コンポーネントに渡していないが、子コンポーネント内でmessageの初期値が入力されているのでthanksが表示される。

### 例3
```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/child';

const Parent = () => {
  return(
		<div>
			<Child
			title = {'Hello'}
			text = {'World'}
			message = {'thanks'}
			/>
		</div>
  );
};

export default Parent;
```

```javascript:child.jsx
// 子コンポーネント（components/child.js）
import React from "react";

const Child = ({title = 'こんにちは', text = 'ようこそ', message = 'ありがとう'}) => {
  return(
		<div>
			<h1>{title}</h1>
			<p>{text}</p>
			<p>{message}</p>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello
World
thanks
```
子コンポーネントに初期値が記述されているが、親コンポーネントの記述により上書きされる。

### 例4
```javascript:parent.jsx
// 親コンポーネント（parent.jsx）
import React from "react";
import Child from './components/child';

const Parent = () => {
  return(
		<div>
			<Child
			title = {'Hello'}
			text = {'World'}
			/>
		</div>
  );
};

export default Parent;
```

```javascript:child.jsx
// 子コンポーネント（components/child.js）
import React from "react";

const Child = ({title = 'こんにちは', text = 'ようこそ', message = 'ありがとう'}) => {
  return(
		<div>
			<h1>{title}</h1>
			<p>{text}</p>
			<p>{message}</p>
		</div>
  );
};

export default Child;
```
出力結果
```
Hello
World
ありがとう
```
今までの複合パターンでした。

# React Hooks
Hook（フック）とはReact 16.8のバージョンで新しくで追加された機能です。
Hookは関数コンポーネントで使うことができる機能で、クラスを書かなくてもstateなどの機能を使えるようになります。

```javascript:古いバージョン
ReactDOM.render(
  <App />,
  document.getElementById("app")
);
```

```javascript:新しいバージョン
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <App />
);
```
これら2つのコードは、Reactのコンポーネントを描画するために使用される異なる方法です。
1つ目のコードでは、`ReactDOM.render()`メソッドを使用して、Reactコンポーネントを指定したHTML要素に描画しています。具体的には、Appコンポーネントをidが"app"であるHTML要素に描画しています。
2つ目のコードでは、`ReactDOM.createRoot()`メソッドを使用して、Reactのルートを作成し、ルートに対してコンポーネントを描画しています。具体的には、Appコンポーネントをidが"root"であるHTML要素に描画しています。
React 18以降では、`ReactDOM.createRoot()`メソッドを使用して、アプリケーション全体をRootにラップすることが推奨されています。Rootにラップすることで、Reactの非同期レンダリング機能（Concurrent Mode）を有効にすることができます。つまり、非同期レンダリングによって、UIのパフォーマンスを改善することができます。
一方、`ReactDOM.render()`メソッドは、Reactの古いバージョンで使用されていた方法であり、非同期レンダリングには対応していません。
つまり、`ReactDOM.createRoot()`メソッドを使用して、アプリケーション全体をRootにラップすることで、より高速でレスポンシブなUIを実現することができます。

## useState
**useStateはHookの1つの機能です。**
「useState」は関数コンポーネントでstateを管理（状態管理）するためのフックです。
関数コンポーネントでは頻繁に使われるフックです。
stateとはコンポーネントが内部で保持する「状態」のことです。
useStateを使うことでコンポーネントの中で「状態」を管理することができます。
これは変数のようなもので、あるデータを保持しておきたいときに使います。
propsは変更できませんがstateは後から変更することができます。

## `import React from "react";`不要？必要？
- Q
`import React from "react";`はReact 16以前は必要、React 17以降は必要なし、コンパイラが自動でインポートしてくれるようになった。
`import React from "react";`はReact 17以降は必要ないという説明があったけど記述消すと上手くいきません、なぜでしょうか？React18.2.0を使用しています。

- A（ChatGPT）
`import React from 'react'`を削除すると、Reactコンポーネントを作成する際に必要なReactオブジェクトへのアクセスができなくなるため、エラーが発生します。React 17以降、Reactオブジェクトへのアクセスが自動的に追加されるようになりましたが、それでもReactオブジェクトを明示的にインポートする必要がある場合があります。したがって、`import React from 'react'`を削除することは推奨されません。
React18.2.0を使用している場合でも、Reactオブジェクトをインポートする必要があるため、`import React from 'react'`が必要になります。このインポートステートメントを省略すると、Reactコンポーネントがレンダリングされなくなり、エラーが発生します。

# その他
## 三項演算子(if文と同等）
`{hoge ? ‘OPEN’ : ‘CLOSE’}`
hogeがtrueならOPEN、falseならCLOSE

## &&で書いた場合
`{hoge && <p>HelloWorld</p>}`
hogeがtrueの場合のみ表示
&&以下はtrueのときのみ表示される

## ??(Null合体演算子)が必要な場合
`{hoge === ‘A’ && ‘B’}`
Null合体演算子は、A ?? Bのとき、値がnullかundefinedの場合以外はA、nullかundefinedの場合はBとなります。
たとえば、配列内で空文字などがあった場合、filterを通すとエラーになってしまうことがあります。
そのようなエラーを防ぐために、null,undefinedのときは、空文字を定義するなどの記述が、Null合体演算子で可能になります。

# 参考リンク
[【React】コンポーネントの基本と使い方を初心者向けに解説！](https://choippo.com/react-component/)
[React Hooks入門](https://ics.media/entry/201106/)