🐟

[エラー][Angular][NgRx] dispatchしていないReducerがdispatchされる

2022/10/22に公開

やりたいこと

下記のように3つのReuducerを定義した。一番下のresetアクションをresetState()のタイミングで実行(dispatch)したい。

Action

export const increment = createAction(
	'[Counter Component] Increment'
);

export const decrement = createAction(
'[Counter Component] decrement'
);

export const reset = createAction(
'[Counter Component] Increment'
);

Reducer

export const counterReducer = createReducer(
  initialState,
  on(CounterActions.increment, (state) => ({...state, countNum: state.countNum + 1})),
  on(CounterActions.decrement, (state) => ({...state, countNum: state.countNum - 1})),
  on(CounterActions.reset, (state) => ({...state, countNum: 0}))
);

Component

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

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

// resetState() {
//   this.store.dispatch(CounterActions.reset());
// }

エラー内容

上記のように、resetState()はコメントアウトしている。
つまり、この段階ではresetアクションはdispacthされないはず。

しかし、Reducerに定義してあるresetが勝手に実行されていました。

原因

原因は、Actionを定義するときのcreateAction()メソッドの第一引数であるtype名です。

このtype名が他のActionのtype名と被ってしまうと、そのActionがdispatchされたタイミングで連動して勝手にresetも実行されていました。

Action

export const increment = createAction(
	'[Counter Component] Increment'
);

export const decrement = createAction(
'[Counter Component] decrement'
);

export const reset = createAction(
'[Counter Component] Increment'     // ← incrementが被っている
);

解決策

type名を被らないように変更します。

Action

export const increment = createAction(
	'[Counter Component] Increment'
);

export const decrement = createAction(
'[Counter Component] decrement'
);

export const reset = createAction(
'[Counter Component] reset'     // ← resetに変更
);

Reducerに処理を定義してもdispacthしないと実行されないはずですが、勝手に実行されていたので混乱しました。

createAction()のtype名はただの名前だと思っていましたが、NgRxが裏で適切なReducerを実行するために識別していたんですね。

何となく理解していたことが、また一つ深い理解に変わりました。

参考

Discussion