React メモ

## 目次
1. [コマンド](#1-コマンド)
1. [JSX](#2-jsx)
1. [props](#3-props)
1. [条件分岐と繰り返し処理](#4-条件分岐と繰り返し処理)
1. [Stateとイベント処理](#5-stateとイベント処理)
1. [ルーティング](#6-ルーティング)

## 1. コマンド

```shell
# create-react-appをインストール
$ npm install -g create-react-app

# 新規作成
$ npx create-react-app [プロジェクト名]

# TSX(JSXのTypeScript版)で作りたい時
# --template typescriptをつける
$ npx create-react-app --template typescript [プロジェクト名]

# 開発サーバー起動
$ npm start

# ビルドしてHTML/CSS/JSファイルを生成
$ npm run build
```

## 2. JSX
* classはclassName, forはhtmlForで書く
* {変数名} の形式で埋め込むことができる

### index.js(最初に呼び出されるファイル)

```jsx
//React関連のライブラリをインポート
import React from 'react';
import ReactDOM from 'react-dom';

//アプリ固有のファイルをインポート
import './index.css';
import App from './App';

//キャッシュのためのサービスをインポート
import reportWebVitals from './reportWebVitals';

//Appコンポーネントを実行
//render(comp, target)
//comp: 出力するコンポーネント
//target: 出力先の要素
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

//サービスを有効化
registerServiceWorker();
```

### コンポーネントファイル

```jsx
//Reactの基本ライブラリをインポート
import React, { Component } from 'react';

//ロゴ画像/スタイルシートをインポート
import logo from './log.svg';
import './App.css';

//Appコンポーネントを定義
class App extends Component {

  //描画内容を準備
  render() {
    return (
      //class → classNameにすること
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
          Learn React
          </a>
        </header>
      </div>
    );
  }
}

//Appクラスをエクスポート
export default App;
```

### React.Fragment(ダミーの要素)

```jsx
//React.Fragmentは最終的な出力には含まれない
ReactDOM.render(
  <React.Fragment>
    <p>あいうえお</p>
    <p>かきくけこ</p>
  </React.Fragment>
  , document.getElementById('root');
);
```

### 属性の設定

```jsx
//属性値前後のクォートは付けない
//href="{url}"だとダメ
const url = 'https://wings.msn.to/';
<a href={url}>Webサイト</a>

//style属性の指定にはオブジェクトを利用する
//オブジェクトリテラルではcamelCase記法に直す
const style = { color: 'Red', backgroundColor: 'Yellow' };
<p style={style}>あいうえお</p>

//属性をまとめて設定
//オブジェクトリテラルと「...」演算子を利用する
const attrs = {
  src: 'http://test/image/aiueo.jpg',
  alt: 'あいうえお',
  title: 'テストあいうえお'
};
<img {...attrs} />
```

### コンポーネントを入れ子にする
```jsx
import React, { Component } from 'react';
//子コンポーネントをインポート
import MyCover from './MyCover';

export default class MyBook extends Component {
  render() {
    return (
      <div>
        {/* MyCoverコンポーネントを呼び出し */}
        <MyCover title={this.props.info.title} />
      </div>
    )
  }
}
```

## 3. props

### propsとは?
単一のオブジェクトとしてこのコンポーネントに渡すオブジェクトのこと。
JSX内で使用する属性情報、子要素を渡すことができる。

```jsx
//コンポーネント側
import React, { Component } from 'react';

export default class MyHello extends Component {
  //プロパティを元に出力を生成
  render(){
    return <div>こんにちは、{this.props.name}さん</div>;
  }
}

//index.js
import MyHello from './MyHello';
...
ReactDOM.render(
  //MyHelloコンポーネントにプロパティを引き渡す
  //この場合は「name」を渡す
  <MyHello name="鈴木" />,
  document.getElementById('root');
);
```

* 「...」演算子を使用することで、オブジェクトの内容を個々の属性にばらすことも可能。

```jsx
const data = {
  name: '鈴木',
  age: 18,
  sex: '男'
};

ReactDOM.render(
  <MyClass {...data} />,
  document.getElementById('root')
);
```

## 4. 条件分岐と繰り返し処理

### 条件分岐

#### 「?:」演算子、「&&」演算子
* 「?:」演算子は、三項演算子のような使い方
* 「&&」演算子は、trueの時だけ出力される

```jsx
//「?:」演算子
{ this.props.isNew ? <MyNew /> : null }

//「&&」演算子
{ this.props.isNew && <MyNew /> }
```

#### 即時関数

```jsx
//関数を使う
//見栄えが悪くなるので、なるべく先に名前付きで関数を作って、それを利用するようにする
{(() => {
  if(this.props.isNew){
    return <MyNew />
  }
})()}
```

### 繰り返し処理
Array#mapメソッドを利用する

```jsx
const data = [
  { name: '鈴木', age: 18, sex: '男', userid=1 },
  { name: '佐藤', age: 20, sex: '女', userid=2 },
};

//index.js
ReactDOM.render(
  //配列dataを使っての繰り返し処理
  <div>
    {data.map((x) => 
      <MyClass {...x} />)}
  </div>
)

//keyプロパティを持たないことによる警告対処のため
//以下のようにkey属性を持つことを推奨
//主キーを持たない場合はkey={index}とするのもOK
//<MyClass {...x} key={x.userid} />
```

## 5. Stateとイベント処理

### Stateとは?
* コンポーネントの状態(state)を管理するオブジェクト。
* stateの値を更新する場合は、setStateを使用する

```jsx
export default class MyState extends Component {

  constructor(props) {
    super(props);

    //Stateの初期値を設定
    this.state = {
      current: new Date()
    }
  }

  //1000ミリ秒おきにStateを更新
  //setStateを使用する
  setInterval(() => {
    this.setState({
      current: new Date()
    });
  }, 1000)

  render() {
    //currentの値をページに反映
    <div>{this.state.current.toLocaleString()}</div>
  }
}
```

### イベント処理
* HTMLではonchange(全て小文字)だが、JSXではonChange(cameCase形式)で書く
* this.関数名.bindでイベント実行時の関数を指定(bindを付けないとエラーになる)

```jsx
//onchangeイベントを起こす
<input id="txtName" type="text" onChange={this.show.bind(this)} />

//アロー関数で指定する場合
<input id="txtName" type="text" onChange={(e) => this.show(e)}

//引数を渡す場合
show(end, e) {
  console.log(`${e.target.value}${end}`);
}
...
//元々のイベントオブジェクトは、引数リストの末尾に渡される
//end => 'さん'
//e => this
//がそれぞれわたされる
<input id="txtName" type="text" onChange={this.show.bind(this, 'さん')} />
```

### ライフサイクルメソッド
後で書く

## 6. ルーティング

* ルーティング機能用のライブラリとして<strong>React Router</strong>がある

```shell
# React Routerをインストール
$ npm install --save react-router-dom
```

### ルーティングのサンプル

* ルーティング設定は`<Route>`で定義する
  * `<Switch>`で括っているのは、最初に合致した要素だけ出力する、という意味
  * exact属性は、完全一致で判定するという意味
* ルーティング経由でのページ遷移は、`<Link>`で定義する


```jsx
import React, { Component } from 'react';

//ルーティング関連の機能をインポート
import { BrowserRouter as Router, Link, Route, Switch } from 'react-router-dom';

//ルーティングで利用するコンポーネントをインポート
import MyTop from './MyTop';
import MyHello from './MyHello';
import MyArticle from './MyArticle';

export default class App extends Component {
  render() {
    //Router(BrowserRouter)でルーティング機能を有効化
    return(
      <Router>
        <div>
          {/* ルーティング経由のリンクリストを準備 */}
          <ul>
            <li><Link to="/">トップ</Link></li>
            <li><Link to="/hello">Hello</Link></li>
            <li><Link to="/article">公開記事</Link></li>
          </ul>
          <hr />
          
          {/* ルーティング設定(条件にマッチしたコンポーネントを出力) */}
          <Switch>
            <Route exact path="/" component={MyTop} />
            <Route　path="/hello"　component={MyHello}/>
            <Route path="/article" component={MyArticle}/>
          </Switch>
        </div>
     </Router>
    )
  }
}
```

### ルートパラメータ

```jsx
  //リンク
  <Link to="/article/13">記事13</Link>

  //ルートパラメーターを含んだルート
  <Route path="/article/:id" component={MyArticle} />

  //コンポーネント側でルートパラメータを受け取る
  //this.props.match.params.名前で受け取ることが可能
  const id = this.props.match.params.id;

```

### 補足
* `<Route>`にてpathを書かない場合、全てのURLにマッチする、という書き方ができる