【React入門】学習メモ #1

この記事は[React Advent Calendar 2020](https://qiita.com/advent-calendar/2020/react) 16日目の記事です。
簡単に自己紹介いたしますと、2020/7月にプログラマに転身したひよっこです。この記事を書く経緯としては、自社HPの改修やら、その他フロントエンド開発でReactを触る機会があり、「ちゃんとReactに入門しよう！」と思い、この記事を書くことになりました。

# はじめに

React学習の備忘録です。
間違い等ございましたら、ご指摘いただけますと幸いです

## JSXとは

公式ドキュメント参照
> JavaScript の構文の拡張です。UI がどのような見た目かを記述するために、React とともに JSX を使用することを私たちはお勧めしています。JSX はテンプレート言語を連想させるでしょうが、JavaScript の機能を全て備えたものです。

Reactを扱う上でJSXは必須という訳ではないようですが、
ここでは、「**JSXを使うとReactを簡単に表現できる**んだなぁ」くらいに思って頂いて大丈夫かと思います。

## JSXの特徴や記法

### return内に複数の要素を記述しない

```App.jsx
render() {
  return(
    <h1>Hello React</h1>
    <h2>Hello Qiita</h2>
    <h3>Hello World</h3>
  );
}
```

上記のように、return内に複数の要素を記述すると下記のエラーが発生します。

```
JSX 式には 1 つの親要素が必要です。
```

上記の問題を解決するためには、下記のように**一つの要素にまとめる**必要があります。

```App.jsx
render() {
  return(
    <div>
      <h1>Hello React</h1>
      <h2>Hello Qiita</h2>
      <h3>Hello World</h3>
    </div>
  );
}
```

### コメント

```App.jsx
render() {
  return(
    <div>
      {/* この部分はコメントです */}
    </div>
  );
}
```

### 自己終了タグ

JSXでは必ずHTMLの終了タグが必要です。
多くのHTMLタグは終了タグは付いていますが、終了タグを記述する必要がないタグも存在します。

- img
- input
- link
- area

上記のような`終了タグ`を記述する必要がないタグにはタグの終わりに`「/」`を付けてあげることで解決します。

```App.jsx
render() {
  return(
    <div>
      <img src='https://hogehoge.com/piyopiyo.jpg' />
    </div>
  );
}
```

### クラス名

JSXでは`「className='クラス名'」`と記述します。

```App.jsx
render() {
  return(
    <div>
      <h1 class='msg'>Hello World</h1>  {/* bad */}
      <h1 className='msg'>Hello React!!</h1>  {/* Good */}
    </div>
  );
}
```

### JSXの中にJSを埋め込む

JSXにJSを埋め込む際は`中括弧{}`で囲む。
中括弧の中ではJavaScriptとして認識されます。

```App.jsx
render() {
  const msg = 'Hello React!!';
  return(
    <div>
      { msg }
    </div>
  );
}
```

タグの属性の値も、同様に`中括弧{}`を使ってJavaScriptを記述できる

```App.jsx
render() {
  const imgUrl = 'https://hogehoge.com/piyopiyo.jpg';
  return(
    <div>
      <img src={ imgUrl } />
    </div>
  );
}
```

## クリックと表示の切り替え

例：ボタンをクリックしたら、画面の表示が切り替わる

上記のようなよく見かけるパターンは`イベント`と`state`を使って実装します。
イベント：**「何かが起きたときに、処理を実行するように指定」**すること。
state：**「ユーザーの動きに合わせて変わる値」**のこと。

## イベントの記述方法

```
イベント名 = {() = { 関数() }}
```

### onClickイベント

onClickイベントはユーザーが要素をクリックしたときにイベントを発火させる。
下記の例では、**ボタンをクリックしたらHello React!!**とアラートを出します。

```App.jsx
render() {
  return(
    <div>
      <button onClick={() => alert('Hello React!!')}>Click</button>
    </div>
  );
}
```

### state

**state**とは、`ユーザーの動きに合わせて変わる値`のことです。
stateが変更されるタイミングで再レンダリングが行われます。

以下、引用
>
- mutable data (可変のデータ)
- maintained by component (コンポーネントによって保持)
- can change it (変更可)
- should be considered private (プライベートであるべき)
>
State は可変のデータです。State の変更は、仮想DOMとの差分をとり、実際のDOMを更新し、コンポーネントを再描画するための基本的な方法となっています。


### state定義

stateは`constructor内でオブジェクトとして定義`する
※下記は、クラスコンポーネントの記述

```App.jsx
class App extends React.Component {
  consttuctor (props) {
    super(props);
    this.state = {  //ここから
      name: 'masa',
      age: 21
    };  //ここまで
  }
}
```

### state取得

`this.state`で取得できる。
定義したstateのnameプロパティの値が欲しければ、`this.state.name`で取得できる

```App.jsx
render() {
  return(
    <div>
      <h1>名前は、{ this.state.name }です</h1>
      <h1>年齢は、{ this.state.age }です</h1>
    </div>
  );
}
```

### state変更

stateの変更は`setState`で変更できる。

```
this.setState({ プロパティ名: 変更する値 })
```

下記では、ボタンを二つ用意し、それぞれのボタンを押下すると表示されている名前と年齢が切り替わる処理になります。

```App.jsx
render() {
  return(
    <div>
      <h1>名前は、{ this.state.name }です</h1>
      <h1>年齢は、{ this.state.age }です</h1>
      <button onClick={() => this.setState({ name: 'masahiro', age: 23 })}>masahiro</button>
      <button onClick={() => this.setState({ name: 'masanobu', age: 28 })}>masanobu</button>
    </div>
  );
}
```

### state変更の注意点

Reactでは、「**stateの値の直接代入することで値を変更してはいけない**」といった決まりがあります。
よって、以下のようなケースはエラーとなります。
stateを変更する際は`setState`を使いましょう。

```
this.state = { name: 'masahiro' };  //エラー
this.state.name = 'masahiro';  //エラー

this.setState({ name: 'masahiro' })  //Good
```

## カウントアップ機能を作成

順序としては、以下の通り

- カウントされるstateを定義
- stateを表示
- stateを変更するメソッドを定義
- ボタンに**onClick**イベントを用意し、上記で定義したメソッドを呼び出す


### stateの定義

まず、カウントされるstateを定義します。
カウントの初期値は0です。

```App.jsx
constructor(props) {
  super(props);
  this.state = {
    count: 0
  };
}
```

### stateの表示

定義したstateを表示する。

```App.jsx
render() {
  return(
    <div>
      { this.state.count }
    </div>
  );
}
```

### stateを変更するメソッドを定義

呼び出したときに、stateを変更してくれるメソッドを定義します。

```App.jsx
// カウントアップするメソッド
handleClickCountUp() {
  this.setState({count: this.state.count + 1});
}
```

### クリックイベントでメソッドを呼び出す

**onClick**イベントと組み合わせて上記で定義したメソッドを呼び出します

```App.jsx
<button onClick = {() => {this.handleClickCountUp()}} >+</button>
```

### 成果物

```App.jsx
class Sample extends React.Component {
  constructor(props) {
    super(props);
    // stateの定義
    this.state = {
      count: 0
    };
  }

  // カウントアップするメソッド
  handleClickCountUp() {
    this.setState({count: this.state.count + 1});
  }

  render() {
    return(
      <div>
        <h1>
          {/* stateの表示 */}
          { this.state.count }
        </h1>
        {/* クリックイベント */}
        <button onClick = {() => {this.handleClickCountUp()}} >+</button>
      </div>
    );
  }
}
```

## 番外編~ifでカウントを制御する~

上記で作成したカウントアップするプログラムにifでカウントを制御してみる

- if：countが15以上で
- this.setState：countを0にする

```App.jsx
// カウントアップするメソッド
handleClickCountUp() {
  this.setState({count: this.state.count + 1});

  // ifでカウント制御
  if (this.state.count >= 15) {
    this.setState({count: 0});
  }
}
```

# 備考

良ければ、続きの記事も見て頂けますと幸いです。

[【React入門】学習メモ #2](https://qiita.com/masa99_it/items/ebb8dafc9c49a7c89fd8)
[【React入門】学習メモ #3](https://qiita.com/masa99_it/items/b9531d4b58c8ba8f6cd8)