【React.js】第一回 Reactでアプリ開発! 〜React・ReactHooks・Reduxを一気に学ぶぜ編〜

JavaScript
マイケル
マイケル
みなさんこんにちは!
マイケルです!
エレキベア
エレキベア
クマ〜〜〜〜
マイケル
マイケル
最近仕事でフロント周りを触ることが多くなってきたので、
今回から勉強も兼ねて React を使ったアプリ開発シリーズを始めてみます!
エレキベア
エレキベア
Reactってよく聞くクマね〜〜〜
マイケル
マイケル
Vue.js、Angular.js、React.js が三大JavaScriptフレームワークと呼ばれているけど、Reactは世界で一番人気のあるJavaScriptフレームワークなんだ!
エレキベア
エレキベア
日本では一番人気じゃないクマね
マイケル
マイケル
に、日本ではVue.jsと五分五分みたいだよ・・・。
とりあえず今後の流れとしては下記のような順番で進めていこうと思うよ。
Reactアプリ開発シリーズの今後の予定
  • 第一回 React、ReactHooks、Reduxの基礎知識
  • 第二回 React・TypeScriptの環境構築
  • 第三回 APIを使った実践的なWebアプリ開発
マイケル
マイケル
第一回では簡単に使える環境でReact周辺技術にざっくり触れて
第二回ではReact・TypeScript環境を一から構築
第三回でAPIとの連携を含めた実践的なアプリ開発
をしていこうと思っています!
マイケル
マイケル
余力があれば サーバサイドレンダリングやNext.jsReactNativeを使ったネイティブアプリ開発 等にも触れていきたいですが、そこまで(僕の気持ちが)持つか分かりません・・・。
エレキベア
エレキベア
(そこはがんばれクマ・・・。)
マイケル
マイケル
Reactにはややこしい単語や概念もたくさんありますが、
簡単なアプリを少しずつ修正していくことでReact、ReactHooks、Reduxまでの概要を一気に学びます
マイケル
マイケル
ざっくりした箇所も多々あると思うので、
分かりづらいところがあれば都度調べながら進めてみてください・・・!
エレキベア
エレキベア
(投げやりクマ・・・)
そんなにややこしいのクマね・・・。
マイケル
マイケル
ああ・・・。
(記事を分けるのがめんどくさかったとは言えない・・・。)
スポンサーリンク

参考書籍

マイケル
マイケル
今回学習するにあたり、下記書籍を参考にさせていだきました!

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで

マイケル
マイケル
「情報が古い」とのレビューが多々ありますが、Reactの基本からReduxの概念まで書いてあるかつ量も多くないので個人的には分かりやすかったです。
この情報に加えて、今の実装方法(ReactHooks等)を勉強すれば一通り通れるので、古い実装を調べながら直せるなら大丈夫だと思います!
マイケル
マイケル
それから「入門ではない」というレビューも多々ありましたが、JavaScriptをある程度かけるレベルならいけそうな気はしました。
何も知らない状態での1冊目だと確かにきついかもしれません・・・。
エレキベア
エレキベア
クマは理解できたクマ〜〜〜
マイケル
マイケル
(すごいクマだ・・・。)

用語説明

マイケル
マイケル
それでは触る前に、ざっくりと用語について説明します!

React

マイケル
マイケル
ReactはFacebook社が開発しているJavaScriptです。
公式サイトで ユーザインターフェース構築のための JavaScript ライブラリ と書かれている通り、WebのUIを作ることに特化したライブラリです!

React公式サイト

エレキベア
エレキベア
Facebookはクマもやってるクマ〜〜
マイケル
マイケル
大きな特徴としては下記のようなものがあります!


・JSX
 JSXという形式を使うことで、HTMLのような構文で記述することが可能。

import {Component} from 'react';

class App extends Component {
  render() {
    return <h1>Hello, Michael!!</h1>;
  }
}
export default App;
↑HTMLのような構文で記載することができる


・仮想DOM
 React内で別のDOMを保持しているようなイメージで、差分だけレンダリングすることでパフォーマンスがよい。

エレキベア
エレキベア
UI構築に特化しているクマね〜〜

ReactHooks

マイケル
マイケル
ReactHooksはReact 16.8から追加された機能で、これまでクラスコンポーネントでしか使えなかったReactの機能を関数コンポーネントで使えるようにしたものになります!

フックの導入-React

エレキベア
エレキベア
全然分からんクマ・・・。
マイケル
マイケル
これは書きながらイメージを覚えていこう!

Redux

マイケル
マイケル
ReduxはReactと一緒によく使われるアーキテクチャで、Flux というアーキテクチャをベースにしています。
マイケル
マイケル
Fluxは下記のように、dispatchでactionを実行し、Viewに反映させるという動きになっています。
ScreenShot 2021 07 04 15 19 38
↑Fluxアーキテクチャ
エレキベア
エレキベア
シンプルな動きクマね
マイケル
マイケル
Reduxも基本は同じ動きとなりますが、加えてstateを管理するReducerが登場します。

Redux公式サイト

ScreenShot 2021 07 07 0 02 52
↑Reduxのイメージ
マイケル
マイケル
dispatchで実行したactionの結果(state)をReducerで管理するようなイメージですね・・・。
エレキベア
エレキベア
ReduxではReducerを使用するクマね
(意味がわからんクマ)
マイケル
マイケル
ちなみに現在は、画像に写っているcontainerを作成しなくても、ReactHooksを使うことによりdispatch実行することができるようになっています。
こちらも後々見ていきましょう!

TODOアプリを作る

マイケル
マイケル
いろいろ説明しましたが、言葉だけではよく分からないと思うので、
手を動かしながら感覚を掴んでいきましょう!
マイケル
マイケル
作るのは簡単なTODOアプリで、入力したタスクが下に追加されていくというだけのものになります!
ソースコードはGitHubにあげてあるのでご自由にお使いください。

[対象フォルダ]
masarito617/react-study – GitHub
 - 01_todo-app-react
 - 02_todo-app-react-hooks
 - 03_todo-app-react-redux

01 todo simple
↑今回作成するアプリ
マイケル
マイケル
ちなみにReact公式ページでもチュートリアルが公開されているため、
こちらを一通りやってから始めると理解がスムーズになると思います!

チュートリアル:Reactの導入

エレキベア
エレキベア
さすがFacebookクマ〜〜

雛形の作成

マイケル
マイケル
それではまず、自分の環境にnode.jsをインストール後、下記コマンドを実行しましょう!
インストール方法については「nodejs インストール」等でググれば溢れるほど出るのでここでは割愛します!
エレキベア
エレキベア
(適当クマ・・・。)
// Reactのベースアプリを作成
npx create-react-app react-todo-app
マイケル
マイケル
create-react-app はReactアプリの雛形を作ってくれる便利コマンドで、
必要なパッケージがあらかじめインストールされています!
{
  "name": "react-todo-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

↑必要なパッケージがあらかじめインストールされている

マイケル
マイケル
作成が完了したら npm start を実行してアプリを起動してみましょう!
// アプリ内に移動
cd react-todo-app
// アプリ起動
npm start
マイケル
マイケル
実行後、http://localhost:3000にアクセスすると画面が出てくると思いますが、これがベースアプリとなります!

ScreenShot 2021 07 02 23 42 02
↑実行後の画面

エレキベア
エレキベア
簡単クマ〜〜〜〜

Reactのみで実装

マイケル
マイケル
それではこれを修正して、Reactのみを使った実装でアプリを作っていきます!
Hello, Worldの表示
マイケル
マイケル
TODOアプリに入る前にまずはHello, Worldを表示してみましょう。
src配下のファイルを下記のみ残して修正しましょう!
.
└── src
    ├── App.js
    └── index.js

↑修正後のファイル構成

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
function App() {
  return <h1>Hello, Michael!!</h1>
}
export default App;
ScreenShot 2021 07 03 0 06 53
マイケル
マイケル
修正後にアプリを実行するとHello, Worldが表示されると思います。
Reactではこのようにタグを返すことで画面を構成することができます!
エレキベア
エレキベア
(Worldじゃないクマ・・・。)
マイケル
マイケル
ちなみに関数ではなくクラスで書くと下記のようになります。
ReactHooksが出た現在ではほぼ使わないですが、次はHooksを使わずにstateを管理をするため、こちらの書き方で記述します!
import {Component} from 'react';

class App extends Component {
  render() {
    return <h1>Hello, Michael!!</h1>;
  }
}
export default App;
↑クラスを使用した記述
エレキベア
エレキベア
関数で記述するやり方とクラスで記述するやり方がある クマね
TODOアプリの作成
マイケル
マイケル
次はついにTODOアプリを作っていきます!
ScreenShot 2021 07 03 13 53 19
マイケル
マイケル
タスクの入力エリアをTodoInput.js、タスク一覧をTodoList.js
として、下記のようなファイル構成にします。
.
└── src
    ├── TodoInput.js
    ├── TodoList.js
    ├── App.js
    └── index.js
マイケル
マイケル
これらのコンポーネント間で値の受け渡し等を行うのですが、
Reactにはprops、stateという概念があり、下記のような関係になっています。


・props
 →コンポーネントの上位階層から渡すことのできる値。
・state
 →コンポーネント内で管理する状態。
  変更があると再描画される。

ScreenShot 2021 07 07 22 11 28
↑props、stateのイメージ
マイケル
マイケル
この関係を意識しながら実装してみましょう!
import {Component} from 'react';
import TodoInput from "./TodoInput";
import TodoList from "./TodoList";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tasks: [
        { title: '寝る', id: 1 },
      ],
      sequenceId: 1,
    };
    this.addTodoItem = this.addTodoItem.bind(this);
    this.resetTodoList = this.resetTodoList.bind(this);
  }

  /* タスク追加処理 */
  addTodoItem(title) {
    // state取得
    const {tasks, sequenceId} = this.state;
    // タスクの追加
    let uniqueId = sequenceId + 1;
    tasks.push({
      title,
      id: uniqueId,
    });
    // state再設定
    this.setState({tasks: tasks, sequenceId: uniqueId});
  }

  /* タスク一覧リセット処理 */
  resetTodoList() {
    this.setState({
      tasks: [],
      sequenceId: 0,
    });
  }

  render() {
    return (
        <div>
          <h1>TODO☆アプリ</h1>
          <button onClick={this.resetTodoList}>リセット</button>
          <TodoInput addTodo={this.addTodoItem} />
          <TodoList tasks={this.state.tasks} />
        </div>
    );
  }
}
export default App;
import {Component} from 'react';

class TodoInput extends Component {
    constructor(props) {
        super(props);
        // stateの定義とbind
        this.state = {
            inputValue: '',
        };
        this.inputValueChange = this.inputValueChange.bind(this);
        this.addButtonClick = this.addButtonClick.bind(this);
    }

    /* テキスト変更時のイベント */
    inputValueChange(e) {
        this.setState({
            inputValue: e.target.value,
        });
    }

    /* ボタン押下時のイベント */
    addButtonClick() {
        const inputValue = this.state.inputValue;
        this.props.addTodo(inputValue);
    }

    render() {
        return (
            <div>
                <input placeholder="タスクを入力するクマ" value={this.state.inputValue} onChange={this.inputValueChange} />
                <button onClick={this.addButtonClick}>追加</button>
            </div>
        );
    }
}
export default TodoInput;
function TodoList(props) {
    // tasksの内容から子要素を生成
    const todoItems = props.tasks.map(task => {
        return <li key={task.id}>{task.title}</li>;
    });
    return (
        <div>
            <ul>
                {todoItems}
            </ul>
        </div>
    );
}
export default TodoList;
マイケル
マイケル
ソースを見ると TodoInput.js内で入力された値をstateで管理し、
App.jsから各コンポーネントへpropsで関数や変数を渡しているのが分かるかと思います!
01 todo simple
↑入力したタスクが一覧に追加される
マイケル
マイケル
これでとりあえずは動作するようになりました!
エレキベア
エレキベア
やったクマ〜〜〜

ReactHooksを使用した記述

マイケル
マイケル
次は作ったTODOアプリを、ReactHooksを使って書き直していきます!
マイケル
マイケル
冒頭でも軽く説明しましたが、ReactHooksを使うとクラスコンポーネントでしか使えなかったReactの機能を関数コンポーネントで使えるようになります!
エレキベア
エレキベア
クラスで出来るならそれでいいのではないかクマ?
マイケル
マイケル
関数コンポーネントの方がコードの見通しがよくなるのもあるし、便利なフックも増えてきているからこっちの方がメリットが多いんだ!
マイケル
マイケル
それからこの後説明する Redux でもReactHooksと組み合わせることでより簡潔に書くことができます。
エレキベア
エレキベア
Hooksを使うのが主流になっているクマね
マイケル
マイケル
ひとまずは一番使うことが多いであろうuseStateを使ってみましょう!
これを使うとクラスでなくてもstate管理をすることができます!
import {useState} from 'react';
import TodoInput from "./TodoInput";
import TodoList from "./TodoList";

function App() {
  // state取得
  const [tasks, setTasks] = useState([{ title: '寝る', id: 1 }]);
  const [sequenceId, setSequenceId] = useState(1);

  /* タスク追加処理 */
  const addTodoItem = (title) => {
    // タスクの追加
    let uniqueId = sequenceId + 1;
    tasks.push({
      title,
      id: uniqueId,
    });
    // state再設定
    setTasks(tasks);
    setSequenceId(uniqueId);
  }

  /* タスク一覧リセット処理 */
  const resetTodoList = () => {
    setTasks([]);
    setSequenceId(0);
  }

  return (
      <div>
        <h1>TODO☆アプリ</h1>
        <button onClick={resetTodoList}>リセット</button>
        <TodoInput addTodo={addTodoItem} />
        <TodoList tasks={tasks} />
      </div>
  );
}
export default App;
import {useState} from 'react';

function TodoInput(props) {
    // state取得
    const [inputValue, setInputValue] = useState('');

    /* テキスト変更時のイベント */
    const inputValueChange = (e) => {
        setInputValue(e.target.value);
    }

    /* ボタン押下時のイベント */
    const addButtonClick = () => {
        props.addTodo(inputValue);
    }

    return (
        <div>
            <input placeholder="タスクを入力するクマ" value={inputValue} onChange={inputValueChange} />
            <button onClick={addButtonClick}>追加</button>
        </div>
    );
}
export default TodoInput;
function TodoList(props) {
    // tasksの内容から子要素を生成
    const todoItems = props.tasks.map(task => {
        return <li key={task.id}>{task.title}</li>;
    });
    return (
        <div>
            <ul>
                {todoItems}
            </ul>
        </div>
    );
}
export default TodoList;
マイケル
マイケル
このように
[変数名, set変数名] = useState(デフォルト値);
とすることでStateを取り出すことができます!
エレキベア
エレキベア
思ったより簡単に使えるのクマね
マイケル
マイケル
基本的にインポートするだけで使えるね!
下記は更にuseContext、useCallback を導入してみた例です!


useContext
 →propsを使わずに子要素に値を渡すことができる
useCallback
 →関数をキャッシュし、引数が変化した時のみ実行することができる

import React, {useState, useCallback} from 'react';
import TodoInput from "./TodoInput";
import TodoList from "./TodoList";

export const TodoContext = React.createContext();

function App() {
  // state取得(このようにまとめて書くこともできる)
  const [state, setState] = useState({tasks: [{ title: '寝る', id: 1 }], sequenceId: 1});

  /* タスク追加処理 */
  const addTodoItem = useCallback((title) => {
      // タスクの追加
      let uniqueId = state.sequenceId + 1;
      state.tasks.push({
        title,
        id: uniqueId,
      });
      // state再設定
      setState({tasks: state.tasks, sequenceId: uniqueId});
  }, [state]);

  /* タスク一覧リセット処理 */
  const resetTodoList = useCallback(() => {
      setState({tasks: [], sequenceId: 0});
  }, [state]);

  return (
      <TodoContext.Provider value={{addTodo: addTodoItem, tasks: state.tasks}}>
        <h1>TODO☆アプリ</h1>
        <button onClick={resetTodoList}>リセット</button>
        <TodoInput />
        <TodoList />
      </TodoContext.Provider>
  );
}
export default App;
import {useContext} from 'react';
import {TodoContext} from "./App";

function TodoList() {
    const todoContext = useContext(TodoContext);

    // tasksの内容から子要素を生成
    const todoItems = todoContext.tasks.map(task => {
        return <li key={task.id}>{task.title}</li>;
    });

    return (
        <div>
            <ul>
                {todoItems}
            </ul>
        </div>
    );
}
export default TodoList;
import {useState, useContext} from 'react';
import {TodoContext} from "./App";

function TodoInput() {
    const todoContext = useContext(TodoContext);

    // state取得
    const [inputValue, setInputValue] = useState('');

    /* テキスト変更時のイベント */
    const inputValueChange = (e) => {
        setInputValue(e.target.value);
    }

    /* ボタン押下時のイベント */
    const addButtonClick = () => {
        todoContext.addTodo(inputValue);
    }

    return (
        <div>
            <input placeholder="タスクを入力するクマ" value={inputValue} onChange={inputValueChange} />
            <button onClick={addButtonClick}>追加</button>
        </div>
    );
}
export default TodoInput;
マイケル
マイケル
このように便利な機能を簡単に使うことができるのが
Hooksの魅力です!
エレキベア
エレキベア
便利クマ〜〜〜〜

Reduxスタイルで書く

マイケル
マイケル
最後にReduxを使って修正してみようと思います!
Reduxは冒頭でも説明した通り、下記のようなアーキテクチャになります。
ScreenShot 2021 07 07 0 02 52
↑Reduxのイメージ
マイケル
マイケル
今回はTodoList.jsとTodoInput.jsは TodoApp.js というコンポーネントにまとめて、ReducerとActionを追加で作ってみましょう!
マイケル
マイケル
なおContainerについては、useDispatchuseSelectorというHooksを使用することによって作成せずに実現できます。
エレキベア
エレキベア
これがさっき言ってたメリットクマね
マイケル
マイケル
それではReduxを使うためにパッケージをインストールして
下記のファイル構成にしましょう!
npm install --save redux react-redux

↑インストール

.
└── src
    ├── actions
    │   └── TodoApp.js
    ├── components
    │   └── TodoApp.js
    ├── reducers
    │   └── TodoApp.js
    └── index.js
↑ファイル構成
マイケル
マイケル
Reduxの役割ごとにフォルダを分けるのは一番多いやり方ですが、その他にもDucksパターンという分け方もあります。気になる方はこちらも調べてみましょう。
マイケル
マイケル
ファイルを作成したら下記に修正します!
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import TodoApp from './components/TodoApp';
import todoAppReducer from "./reducers/TodoApp";

// storeの作成
const store = createStore(todoAppReducer);

ReactDOM.render(
  <Provider store={store}>
    <TodoApp />
  </Provider>,
  document.getElementById('root')
);
import {useDispatch, useSelector} from "react-redux";
import {inputTask, addTask, resetTask} from "../actions/TodoApp";

function TodoApp() {
    const dispatch = useDispatch();
    const task = useSelector(state => state.task);
    const tasks = useSelector(state => state.tasks);

    return (
      <div>
        <h1>TODO☆アプリ</h1>
        <button onClick={() => dispatch(resetTask())}>リセット</button>
        <br/>
        <input placeholder="タスクを入力するクマ"
               onChange={(e) => dispatch(inputTask(e.target.value))} />
        <button onClick={() => dispatch(addTask(task))}>追加</button>
        <ul>
            {
                tasks.map((item, i) => {
                    return <li key={i}>{item}</li>;
                })
            }
        </ul>
      </div>
    );
}
export default TodoApp;
export const inputTask = (task) => ({
    type: 'INPUT_TASK',
    payload: {
        task
    }
});
export const addTask = (task) => ({
    type: 'ADD_TASK',
    payload: {
        task
    }
});
export const resetTask = () => ({
    type: 'RESET_TASK',
    payload: {}
});
const initialState = {
    task: '',
    tasks: []
};
export default function todoAppReducer(state = initialState, action) {
    switch (action.type) {
        case 'INPUT_TASK':
            return {
                ...state,
                task: action.payload.task
            };
        case 'ADD_TASK':
            return {
                ...state,
                tasks: state.tasks.concat([action.payload.task])
            };
        case 'RESET_TASK':
            return {
                ...state,
                tasks: []
            };
        default:
            return state;
    }
}
マイケル
マイケル
Actionを実行したらその結果のstateをReducerが保存する、
というように各ソースの役割がはっきりしたかと思います!
エレキベア
エレキベア
確かにごちゃごちゃ感は無くなった気がするクマね
マイケル
マイケル
この量だとあまり恩恵は感じないかもしれないけど、規模が大きくなるほど管理のしやすさが上がると思うので、アーキテクチャの導入はおすすめです!
Redux Middleware
マイケル
マイケル
更にReduxを使うもう一つのメリットとして、ReduxMiddlewareという機能を使うことができる、というものがあります!
マイケル
マイケル
これはActionがディスパッチされてからReducerに遷移するまでの処理のことで、公開されているものを使うことも、自分で作ることもできます。
エレキベア
エレキベア
Reduxにも便利機能があるクマね
マイケル
マイケル
今回は有名な redux-logger、redux-thunk の2つを使ってみましょう!
npm install --save redux-logger redux-thunk

↑ミドルウェアをインストール

・ログ出力

マイケル
マイケル
まずは1つ目のredux-loggerから!
こちらはActionのログ出力をする機能になります。
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, applyMiddleware} from 'redux';
import {Provider} from 'react-redux';
import {logger} from "redux-logger/src";
import TodoApp from './components/TodoApp';
import todoAppReducer from "./reducers/TodoApp";

// storeの作成
const store = createStore(
    todoAppReducer,
    applyMiddleware(logger)
);

ReactDOM.render(
  <Provider store={store}>
    <TodoApp />
  </Provider>,
  document.getElementById('root')
);
↑ミドルウェアの登録
マイケル
マイケル
上記のように実装すると、コンソールにActionのログが出力されるようになります!
ScreenShot 2021 07 05 21 33 08
↑ログが出力されるようになる
エレキベア
エレキベア
こんな簡単に使えるクマね

・非同期処理

マイケル
マイケル
そして次にredux-thunk
こちらは非同期のActionを実行することができる機能です!
マイケル
マイケル
下記は非同期で数秒待ってから処理を行うように修正したものです!
thunkを使うことでdispatch, getStateを引数に取ることができるようになり、非同期処理の後にActionを実行できる仕組みです!
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, applyMiddleware} from 'redux';
import {Provider} from 'react-redux';
import {logger} from "redux-logger/src";
import thunk from "redux-thunk";
import TodoApp from './components/TodoApp';
import todoAppReducer from "./reducers/TodoApp";

// storeの作成
const store = createStore(
    todoAppReducer,
    applyMiddleware(logger, thunk)
);

ReactDOM.render(
  <Provider store={store}>
    <TodoApp />
  </Provider>,
  document.getElementById('root')
);
export const inputTask = (task) => ({
    type: 'INPUT_TASK',
    payload: {
        task
    }
});
export const addTask = (task) => ({
    type: 'ADD_TASK',
    payload: {
        task
    }
});
export const resetTask = () => ({
    type: 'RESET_TASK',
    payload: {}
});

// 非同期Action
// thunkを使うことでdispatchとstateを引数に取ることができる!
export const asyncAddTask = (task) => {
    // 引数にdispatch、getStateを受け取ることができる
    return (dispatch, getState) => {
        setTimeout(() => {
            // 非同期処理が完了後にActionを実行
            dispatch(addTask(task));
        }, 500);
    };
}
import {useDispatch, useSelector} from "react-redux";
import {inputTask, addTask, resetTask, asyncAddTask} from "../actions/TodoApp";

function TodoApp() {
    const dispatch = useDispatch();
    const task = useSelector(state => state.task);
    const tasks = useSelector(state => state.tasks);

    return (
      <div>
        <h1>TODO☆アプリ</h1>
        <button onClick={() => dispatch(resetTask())}>リセット</button>
        <br/>
        <input placeholder="タスクを入力するクマ"
               onChange={(e) => dispatch(inputTask(e.target.value))} />
        <button onClick={() => dispatch(asyncAddTask(task))}>追加</button>
        <ul>
            {
                tasks.map((item, i) => {
                    return <li key={i}>{item}</li>;
                })
            }
        </ul>
      </div>
    );
}
export default TodoApp;
エレキベア
エレキベア
非同期Actionはよくあるし多用しそうクマね
マイケル
マイケル
thunkの他にもredux-sagaというミドルウェアもあり、こちらも有名です!
このように便利なミドルウェアがたくさん用意されているのもReduxのメリットです。
エレキベア
エレキベア
クマもミドルウェアになるクマ〜〜〜

おわりに

マイケル
マイケル
というわけでReact関連の基礎知識を一気に通ってみましたが
どうだったでしょうか?
エレキベア
エレキベア
よく分からないところもあるクマが大体イメージは沸いたクマ
マイケル
マイケル
ざっと書いてしまって申し訳ないクマ・・・。
とりあえずまた次回から環境構築、実践的なアプリ制作と進んでいくので
実際に作りながら覚えていきましょう!
エレキベア
エレキベア
まあ付きやってやるクマ
マイケル
マイケル
それでは今日はこの辺で!
アデューー!!
エレキベア
エレキベア
クマ〜〜〜〜


【React.js】第一回 Reactでアプリ開発! 〜React・ReactHooks・Reduxを一気に学ぶぜ編〜 〜完〜

※次回記事はこちら!

コメント