LoginSignup
1
1

More than 3 years have passed since last update.

【Redux】カウントアプリを作りながらReduxを理解しよう!

Last updated at Posted at 2021-03-30

概要

Reduxは状態管理のライブラリです。Reactで状態管理をする方法は色々あります。最近だとHooksのuseContextとかあるけど、まだReduxが使われるケースも多いでしょうってことで、Reduxの使い方についてまとめてみました!最初にReduxの概念の説明して、後半は実際にカウントアプリを作りながらReduxの説明をしていきます

Reduxとは?

Reactではコンポーネントに状態を待たしていましたが、Reduxを使うことでstoreでstateを管理することができます。Reactではstateは子のコンポーネントにしかpropsで渡すことができませんでしたが、下図のようにReduxではstoreを使うことで親のコンポーネントにバケツリレーさせずにstateを渡すことができます

image.png

画像引用元

どんな時に使うのか

  • 大規模なアプリ向けです、大規模なアプリで状態管理を使わないとトップのコンポーネントにstateが集まってしまったり、propsが多くなって扱いづらくなってしまいます。

処理の流れ

  • Action : stateを切り替えたい時のアクションを定義してあります
  • Reducer : actionに応じてstateを変更する処理が書いてあります
  • Store : stateの情報を保持します


画像引用元

上記のように、Action→Reducer→Store→UIに反映の順で処理が進みます

以降は、言葉で説明するよりも実際に作る方が分かりやすいと思うのでカウントアプリを作りながらReduxの使い方を説明していきます

カウントアプリデモ画面

ezgif.com-gif-maker (9).gif

作成手順

1. 環境構築

Create-React-App

$ npx create-react-app アプリ名

インストール

reduxを使うためのライブラリをインストールしていきます

# NPM
$ npm install redux react-redux
# YARN
$ yarn add redux react-redux

redux:redux本体
react-redux:reactでreduxを使うためのライブラリ

確認方法
・ package.jsonのdependenciesで確認できます

※ 今回使用しません
@reduxjs/toolkit
redux-devtools

2. アプリ作成

ディレクトリ構成を編集

srcディレクトリを下記のように変更しましょう。

ディレクトリ構成

src
├── App.js
├── actions
├── index.js
├── reducers
└── store

srcディレクトリ内の今回必要ないファイルを削除して、actionsreducersstoreディレクトリを追加してあります

Action作成

actionsディレクトリにindex.jsファイルを作成して以下のように書き換えます

actions/index.js
export const increment10 = () => {
  return {
    type: 'INCREMENT10',
  };
};
export const increment1 = () => {
  return {
    type: 'INCREMENT1',
  };
};
export const decrement1 = () => {
  return {
    type: 'DECREMENT1',
  };
};
export const decrement10 = () => {
  return {
    type: 'DECREMENT10',
  };
};

上記のように、actionはtypeとゆうプロパティを持っているオブジェクトを返している関数です。次に説明するReducerでtype事に処理を分岐させていきます

Reducer作成

reducersディレクトリにcounter.jsを作成して以下のように書き換えます

counter.js

reducers/counter.js
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT10':
      return state + 10;
    case 'INCREMENT1':
      return state + 1;
    case 'DECREMENT1':
      return state - 1;
    case 'DECREMENT10':
      return state - 10;
    default:
      return state;
  }
};

export default counterReducer;

stateとactionを受け取って、actionのtype事に条件分岐して加算、減算した新しいstateをreturnしています。仮パラメータのstateに0が代入されていますね。これは、stateの初期値を表しています

次に、reducersディレクトリにindex.jsを作成して以下のように書き換えてください

index.js

reducers/index.js
import counterReducer from './counter';
import loggedReducer from './isLogged';
import { combineReducers } from 'redux';

const allReducers = combineReducers({
  counter: counterReducer,
});

export default allReducers;

Reducersをcombine(組み合わせ)しています。
今回、Reducerは1つしか作成していないのでcombineReducersは使わなくても作成できますが、便利なので紹介しときました

Storeを作成

store/index.js
import { createStore } from 'redux';
import allReducers from '../reducers';

const store = createStore(
  allReducers,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
これは、Redux DevTools Extensionを使う時に必要なコードです。とても便利なChrome DevToolsの拡張機能なので最後に紹介します

src/index.jsx

src/index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';

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

Providerでを囲みます。これを書くことでstoreのstateをコンポーネントに渡すことができます、Providerのstore={store}はstore属性に今回作成したstoreを指定して対応させてます

src/App.jsx

それでは実際にApp.jsxに対応させてアプリを完成させます

src/App.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment10, increment1, decrement1, decrement10 } from './actions';

const App = () => {
  const counter = useSelector((state) => state.counter);
  const dispatch = useDispatch();
  return (
    <>
      <h1>Counter: {counter}</h1>
      <button onClick={() => dispatch(increment10())}>+10</button>
      <button onClick={() => dispatch(increment1())}>+1</button>
      <button onClick={() => dispatch(decrement1())}>-1</button>
      <button onClick={() => dispatch(decrement10())}>-10</button>
    </>
  );
};

export default App;

import { useSelector, useDispatch } from 'react-redux'; のuseSelectorとuseDispatchはRedux Hooksと呼ばれるものです。 useSelectorはstoreのstateを取得するためのもの。useDispatchはReducerを呼び出しています。
connect()を使って書いてあるものがあったら古い書き方です
dispatch(increment10())dispatch({type: 'INCREMENT10'})と同じ意味なので書き換えてもらっても構いません。私的にはアクション名の方が分かりやすいです

これでカウントアプリは完成です。最後にRedux DevTools Extensionだけ紹介します!

Redux DevTools Extension

まずはRedux DevTools Extensionのインストールが終わってない場合はRedux DevTools ExtensionのREADME.mdのInstallationにそってインストールしてください。
インストールが終わったらChrome DevToolsを開いてReduxのタブを開いてアプリを実行させstoreのstateを変更してみます

ezgif.com-gif-maker (12).gif

上記のように、左側でアクションのtypeプロパティ、右側でstoreのstateの差分が表示されました。便利ですよね、他にも色々な機能があるのでREADME.mdを読んでみてください

おわりに

Reduxは少し分かりにくいですよね、何か詰まってるところがあれば今回の記事で解消されれば幸いです
参考: redux公式

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1