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 5 years have passed since last update.

【ReactNative+Redux】ActionとReducerの記述を改善?した話

Last updated at Posted at 2019-07-01

はじめに

Typescript+ReactNative+Reduxを勉強中なのですが、
下記のような記述が個人的にはすごく気持ち悪い。

HogeAction.ts
export const HOGE_ACTION_1: string = 'HOGE_ACTION_1';
export const HOGE_ACTION_2: string = 'HOGE_ACTION_2';

export class HogeAction1 {
  type : string = HOGE_ACTION_1;
  data1: string = '';
}

export class HogeAction2 {
  type : string = HOGE_ACTION_2;
  data2: boolean = false;
  data3: number = 0;
}

Reducer側ではtypeを参照してどのActionか判定しているけど、Actionはちゃんと型として定義しているのだからそんなことする必要はないのでは??

と思ったらReducerではActionをanyで受けているのか...

HogeReducer.ts
import {
  HOGE_ACTION_1,
  HOGE_ACTION_2,
  HogeAction1,
  HogeAction2
} from '../HogeAction';
import HogeState from '../HogeState';

// Stateを初期化
const initialState: HogeState = new HogeState();

export default function HogeReducer(state = initialState, action : any){

  if(!action){
    return state;
  }

  switch(action.type){

    case HOGE_ACTION_1:
      // HogeAction1処理...

    case HOGE_ACTION_2:
      // HogeAction2処理...

    default:
      return state;
  }
}

修正後

それならActionBaseというActionの基底クラスを作って、そこで各Actionのインスタンスの区別がつくようにしてあげればいいのでは(言語化すると何言ってるのか分からんので、下記コードを見てください)

ActionBase.ts
export default class ActionBase {
  // コンストラクタ
  constructor(){
  }

  // クラス名
  public type : string = this.getClassName();

  public getClassName() {
    if(!this || !this.constructor){
      return '';
    }
    
    // コンストラクタからクラス名を取得
    const constructorRegex: RegExp =/function (.{1,})\(/;
    const results = (constructorRegex).exec((<any> this).constructor.toString());
    return (results && results.length > 1) ? results[1] : '';
  }
}

getClassName()でインスタンス化した各Actionのコンストラクタ文字列を呼び出してActionを特定している。

typeはActionBaseに持たせておけばよいので、各Actionクラスは純粋に操作するプロパティだけを持たせる。

HogeAction.ts
import ActionBase from './ActionBase';
//export const HOGE_ACTION_1: string = 'HOGE_ACTION_1';
//export const HOGE_ACTION_2: string = 'HOGE_ACTION_2';

export class HogeAction1 extends ActionBase{
  //type : string = HOGE_ACTION_1;
  data1: string = '';
}

export class HogeAction2 extends ActionBase{
  //type : string = HOGE_ACTION_2;
  data2: boolean = false;
  data3: number = 0;
}

Reducerはaction.typeと各Actionクラスの.nameを突合させて判定している。

HogeReducer.ts
import {
  HogeAction1,
  HogeAction2
} from '../HogeAction';
import HogeState from '../HogeState';
import ActionBase from '../ActionBase';

// Stateを初期化
const initialState: HogeState = new HogeState();

export default function HogeReducer(state = initialState, action : ActionBase){

  if(!action){
    return state;
  }

  switch(action.type){

    case HogeAction1.name:
      // HogeAction1処理...

    case HogeAction2.name:
      // HogeAction2処理...

    default:
      return state;
  }
}

これで少しはモヤっとする書き方をせずに済むかも。
もっと良い書き方があれば教えていただければ幸いです。

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?