0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ReactのReduxとは?ユースケースなどまとめ

Last updated at Posted at 2023-10-16

Reduxは、JavaScriptアプリケーションのための予測可能な状態コンテナです。Reactと一緒に使用されることが多いですが、Reactに限定されるものではありません。Reduxは、アプリケーションの状態を一元管理することで、アプリケーションの動作をより予測可能に、安定して、そしてデバッグしやすくします。

Reduxの主な原則は以下の通りです:

  1. シングルソースオブトゥルース(単一の信頼できる情報源): アプリケーションの全状態は、一つのストア内のオブジェクトツリーに保存されます。これにより、状態の管理が容易になり、デバッグやテストが簡単になります。

  2. 状態は読み取り専用: 状態を変更する唯一の方法は、何かが起こったことを示すアクションを発行することです。これにより、ビューまたはコールバックが状態を直接変更することがなくなり、バグや不整合が減少します。

  3. 変更は純粋な関数によって行われる: アクションによって状態ツリーがどのように変更されるかを指定するために、純粋なリデューサー関数を使用します。リデューサーは、前の状態とアクションを取り、次の状態を返します。

Reduxの流れは以下のようになります:

  1. アクションの発行: アプリケーションで何かが起こるたびに、アクションが作成されます。アクションは、発生したイベントのタイプと更新が必要なデータを示すプレーンなオブジェクトです。

  2. リデューサーの実行: アクションが発行されると、Reduxのリデューサー関数が呼び出されます。この関数は、現在の状態とアクションを引数として受け取り、新しい状態を返します。

  3. ストアの更新: リデューサー関数によって返された新しい状態がストアに保存されます。

  4. ビューの更新: ストアの状態が変更されると、UIが新しい状態を反映するように更新されます。

Reduxは、状態管理を中央集中化し、アプリケーションの動作を予測可能にすることで、大規模なアプリケーションや高度にインタラクティブなアプリケーションの開発を容易にします。

実装例

Reduxの基本的な実装例を以下に示します。この例では、シンプルなカウンターアプリケーションを考え、その動作に必要なアクション、リデューサー、そしてストアの設定について説明します。

まず、必要なReduxのライブラリをインストールします。

npm install redux

次に、アクションタイプ、アクションクリエーター、そしてリデューサーを定義します。

// actions.js

// アクションタイプの定義
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';

// アクションクリエーターの定義
export const increment = () => ({
  type: INCREMENT,
});

export const decrement = () => ({
  type: DECREMENT,
});
// reducers.js

import { INCREMENT, DECREMENT } from './actions';

// リデューサーの定義
export const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
};

次に、Reduxストアを作成し、リデューサーを渡します。

// store.js

import { createStore } from 'redux';
import { counterReducer } from './reducers';

// ストアの作成
export const store = createStore(counterReducer);

最後に、UIコンポーネントを作成し、ストアと接続します。

// App.js

import React from 'react';
import { store } from './store';
import { increment, decrement } from './actions';

class App extends React.Component {
  componentDidMount() {
    // ストアの変更を購読し、状態の変更があるたびにUIを更新
    store.subscribe(() => this.forceUpdate());
  }

  handleIncrement = () => {
    store.dispatch(increment());
  };

  handleDecrement = () => {
    store.dispatch(decrement());
  };

  render() {
    return (
      <div>
        <h1>カウント: {store.getState()}</h1>
        <button onClick={this.handleIncrement}>増加</button>
        <button onClick={this.handleDecrement}>減少</button>
      </div>
    );
  }
}

export default App;

このコードは、Reduxの基本的なパターンを示しています。アプリケーションが成長するにつれて、複数のリデューサーを組み合わせたり、非同期アクションを扱うためのミドルウェア(例:redux-thunk)を使用するなど、より複雑なパターンが必要になる場合があります。

ユースケース

Reduxは、JavaScriptアプリケーション用の予測可能な状態コンテナです。Reactと組み合わせて使用すると、アプリケーションの状態を効果的に管理し、コンポーネント間で状態を共有することができます。以下に、ReactのReduxの一般的なユースケースをいくつか示します。

  1. 大規模なアプリケーションの状態管理:

    • 大規模なプロジェクトや、多くの状態を持つアプリケーションでは、Reduxを使用してアプリケーションの状態を一元管理することができます。
  2. 複雑な状態のロジック:

    • アプリケーションに複数の状態が存在し、それらが互いに依存している場合、Reduxはその複雑さを抽象化し、状態の更新をより予測可能にします。
  3. パフォーマンスの最適化:

    • Reduxは、必要に応じて再レンダリングするコンポーネントを選択することで、パフォーマンスの最適化に役立ちます。
  4. 状態の永続性と再現性:

    • Reduxを使用すると、アプリケーションの状態を保存し、必要に応じて以前の状態に戻すことができます。これは、特定の状態をデバッグしたり、アプリケーションの状態を保存して後で再開したりする場合に便利です。
  5. コミュニティとミドルウェアのサポート:

    • Reduxは大規模なコミュニティに支えられており、ロギング、エラー報告、非同期API呼び出し(redux-thunkやredux-sagaなど)といった多くのミドルウェアが利用可能です。

これらのユースケースは、Reduxが提供する状態管理の柔軟性と予測可能性を示しています。ただし、小規模なプロジェクトや状態管理がそれほど複雑でない場合は、ReactのContext APIやReact Queryなどの他のソリューションを検討するのも良いでしょう。

ReactのReduxはAngularだったらどの機能にあたる?

Angularアプリケーションにおける状態管理のための機能は、"NgRx"です。NgRxはReduxの原則に基づいており、Angularアプリケーションのための状態管理ライブラリです。

ReactのReduxと同様に、NgRxもまたFluxアーキテクチャに触発されており、アプリケーションの状態を一元管理するストア、状態を変更するためのアクション、そしてアクションに応じてストアの状態を変更するリデューサーという概念を使用します。

NgRxの主な特徴は以下の通りです:

  1. Observableに基づく: NgRxはRxJSを利用しており、ストアの状態に対する変更をObservableとして提供します。これにより、非同期操作やストリーム処理が容易になります。

  2. Immutability(不変性): NgRxでは、状態は変更可能なオブジェクトではなく、変更されるたびに新しいオブジェクトが作成されます。これにより、パフォーマンスの最適化や変更の追跡が容易になります。

  3. Effects(エフェクト): 非同期処理や副作用のあるアクションを扱うための仕組みです。これにより、API呼び出しやルーティングなどの副作用を効果的に管理できます。

  4. DevToolsのサポート: Reduxと同様に、NgRxもまた開発ツールを提供しており、リアルタイムでの状態の監視、アクションのディスパッチ、過去の状態へのタイムトラベルなどが可能です。

  5. Entity Management: NgRx entityは、コレクションの形でのデータ管理を簡素化するユーティリティを提供します。

これらの機能により、NgRxはAngularアプリケーションにおける複雑な状態管理、データ処理、およびサイドエフェクトの管理に適しています。

AngularでのNgRxの実装例

AngularでReduxのような状態管理を実装するには、通常、NgRxライブラリを使用します。以下に、簡単なNgRxを使用した状態管理の実装例を示します。この例では、単純なカウンターアプリケーションを考え、その状態をインクリメント(増加)またはデクリメント(減少)するアクションを実装します。

まず、NgRxをプロジェクトにインストールする必要があります。コマンドラインで以下のコマンドを実行します:

ng add @ngrx/store

1. アクションの定義

最初に、アプリケーションで使用するアクションを定義します。actionsフォルダを作成し、その中にcounter.actions.tsファイルを作成します:

// counter.actions.ts
import { createAction } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');

2. リデューサーの作成

次に、これらのアクションに応じて状態を変更するリデューサーを作成します。reducersフォルダを作成し、その中にcounter.reducer.tsファイルを作成します:

// counter.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from '../actions/counter.actions';

export const initialState = 0;

const _counterReducer = createReducer(
  initialState,
  on(increment, (state) => state + 1),
  on(decrement, (state) => state - 1),
  on(reset, (state) => 0)
);

export function counterReducer(state, action) {
  return _counterReducer(state, action);
}

3. ストアの設定

アプリケーションモジュールにストアを設定します。app.module.tsに以下を追加します:

// app.module.ts
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './reducers/counter.reducer';

@NgModule({
  // ...
  imports: [
    // ...
    StoreModule.forRoot({ count: counterReducer }),
  ],
  // ...
})
export class AppModule {}

4. コンポーネントでのストアの使用

最後に、コンポーネントでストアを使用して状態を取得し、アクションをディスパッチします。例えば、app.component.tsでは以下のようになります:

// app.component.ts
import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs';
import { increment, decrement, reset } from './actions/counter.actions';

@Component({
  selector: 'app-root',
  template: `
    <button (click)="increment()">Increment</button>
    <div>Current Count: {{ count$ | async }}</div>
    <button (click)="decrement()">Decrement</button>
    <button (click)="reset()">Reset Counter</button>
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  count$: Observable<number>;

  constructor(private store: Store<{ count: number }>) {
    this.count$ = store.pipe(select('count'));
  }

  increment() {
    this.store.dispatch(increment());
  }

  decrement() {
    this.store.dispatch(decrement());
  }

  reset() {
    this.store.dispatch(reset());
  }
}

このコードでは、incrementdecrementresetメソッドがそれぞれのアクションをディスパッチし、count$ Observableは非同期パイプを使用してテンプレート内で現在のカウントを表示します。

これはNgRxを使用した非常に基本的な例ですが、実際のアプリケーションでは、エフェクト(副作用の管理)、セレクター(状態の一部を選択的に取得)、エンティティ(コレクションの管理)など、より高度な機能を使用することが多いです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?