redux-typescriptのサンプルを説明する

# はじめに
Reactは、公式や色々なサイトで詳しくかつ分かりやすく紹介されています。しかし、Reactにはstoreやcomponentなどの色々な要素が入ってきて、説明が長く理解が難しかったです。そのため、単純にサンプルの説明をまとめることで端的に実感を伴った理解となるようにしました。


# 環境
 - node.js: v12.18.2
 - react:17.0.1 
 - typescript:3.8.3


# プロジェクト作成
## プロジェクト作成コマンド
npxコマンドを使用してReactのプロジェクトを作成します。この時に、templateにredux-typescriptを指定することでtypeScriptとデータの保存を楽にするライブラリ（ReduxとRedux Toolkit）がインストールされたプロジェクトが作成されます。

プロジェクト作成コマンド

```

C:\my_program\react>npx create-react-app react-my-app --template redux-typescript

～～　略　～～

  cd react-pi-app
  yarn start

Happy hacking!
```

## プロジェクトの起動
プロジェクト作成コマンドが終了すると、既に実行できる状態なので起動してみます。
起動が完了すると自動的にブラウザにサンプルページが表示されます。

起動コマンド

```

C:\my_program\react>cd react-my-app
C:\my_program\react\react-my-app>yarn serve
```

# サンプルプロジェクトの説明
## フォルダ構成
作成した直後のプロジェクトのフォルダ構成は以下のようになっています。

```
react-my-app\
    |--public\
    |    |--index.html                  //ブラウザで開かれるhtml
    |--src\
         |--app\
         |    |--store.ts                // データを保存・処理するソース
         |--features\
         |    |--counter\
         |        |--Counter.module.css  // 画面に表示される部品のCSS
         |        |--Counter.tsx         // 画面に表示される部品
         |        |--counterSlice.ts     // 画面に表示される部品のデータの処理
         |--App.css                     // 画面のCSS
         |--App.tsx                     // 画面
         |--index.css                   
         |--index.tsx                   // htmlとAppをつなぐソース
```

## ソースの説明
### ブラウザからのソースの流れ
ブラウザから表示したときに以下の流れで処理が読み込まれます。

```
public/index.html
    |--src/index.tsx
    |   |--src/app/store.ts                           // データを保存・処理するソース
    |       |--src/features/counter/counterSlice.tsx  // Counterで使用するデータの処理
    |--src/App.tsx                                    // 画面表示の処理の流れ
    |    |--src/features/counter/Counter.tsx          // Counter部品の画面表示
    |--src/index.css
```


### 最初に読み込まれるソース(public/index.html、src\index.tsx)
ブラウザからアクセスしたときは、最初にpublic/index.htmlが呼び出されます。
Reactはシングルページアプリケーションなので、使用するhtmlは基本的にこれ一つになります。src/index.tsxが実行されindex.htmlのroot要素にスクリプトの内容が適用されます。
サンプルではsrc/index.tsxからsrc/app/store.ts、src/App.tsx、src/index.cssの3つのファイルが読み込まれて実行されます。

``` index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { store } from './app/store';
import { Provider } from 'react-redux';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
```

### データを処理するソース
#### データを取りまとめるソース(src\app\store.ts)
Reactでは、データの保存や変更などデータの処理をまとめたものをstoreと呼んでいます。
サンプルではsrc/index.tsxから呼び出しているsrc/app/store.tsがそれにあたります。
ここでは、src/features/counter/counterSlice.tsxを呼び出してstoreに登録しています。

```store.ts

import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
// Reducerを読み込む
import counterReducer from '../features/counter/counterSlice';

// configureStore内のreducerにcounterキーでcounterReducerを定義する
export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

～～　略　～～
```

#### データの保存や変更などデータの処理をするソース(src/features/counter/counterSlice.tsx)
データの保存や変更などデータの処理をReducerと呼んでいます。さらに、保存するものをstateと呼び、処理するものをActionと呼んでいます。
サンプルでは、src/app/store.tsから呼び出しているsrc/features/counter/counterSlice.tsxがそれにあたります。
counterSliceのActionはincrementという名前で、処理としてはstate内のvalueを+1しています。

```

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { AppThunk, RootState } from '../../app/store';

// ここでstateに保存する形を定義する
interface CounterState {
  value: number;
}
// 初期値を定義する
const initialState: CounterState = {
  value: 0,
};

// Reducerの定義をする
export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: state => {
      state.value += 1;
    },
  },
});

export const { increment } = counterSlice.actions;

export const selectCount = (state: RootState) => state.counter.value;

export default counterSlice.reducer;

```

### Web画面を表示するソース
#### Webのトップ画面のソース(src/App.tsx)
Reactはシングルページアプリケーションであるため、複数のページを用意するのではなく、1つのページの要素を変更することにより複数画面を実現しています。ブラウザからアクセスしたときに表示される内容がこのApp.tsxになります。ここで色々な要素を組み合わせて画面を作っていきます。
サンプルではsrc/features/counter/Counter.tsxのCounterを呼び出して表示しています。

```App.tsx

import React from 'react';
// Counterを読み込む
import { Counter } from './features/counter/Counter';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        {/* 読み込んだCounterを表示 */}
        <Counter />
      </header>
    </div>
  );
}

export default App;
```

#### カウンター部品のソース(src/features/counter/Counter.tsx)
Reactの部品はComponentと呼ばれています。このように細かい部品を使ってページを作っていきます。
counterSlice.tsxで定義したactionとstateのselectCountを呼び出しています。
呼び出したstate内の値をuseSelectorを使用して参照できるようにしています。また、incrementのActionをuseDispatchを使用して呼び出しています。

``` Counter.tsx

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
// Reducerの内容を呼び出す
import {
  increment,
  selectCount,
} from './counterSlice';
// ここで使うcssを呼び込み
import styles from './Counter.module.css';

export function Counter() {
  // このソース内で参照できるようにする
  const count = useSelector(selectCount);
  const dispatch = useDispatch();

  return (
    <div>
      <div className={styles.row}>
        {/* dispatchを使用して呼び出したincrementを実行 */}
        <button
          className={styles.button}
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          +
        </button>
        <span className={styles.value}>{count}</span>
      </div>
    </div>
  );
}
```

# おわりに
ReactはJavaScriptやTypeScriptでシングルページアプリケーション（SPA）を実現するためのフレームワークなため、JavaScript、TypeScript、SPAの知識が事前に必要になるのは当然だと思います。しかし、実際に開発する際はそれらの事前知識が十全にある状態とは限らないので、そういった無茶振りされた方のために極力シンプルにまとめました。次は、サンプルを改造して色々してみようと思います。