LoginSignup
2
2

More than 5 years have passed since last update.

redux-observableで作ったintervalのobservableをHot Module Replacementで止まるようにする

Last updated at Posted at 2018-09-28

epicでintervalを利用するような場合、HMRが効いてるとそのまま動いてしまう。
storeはHMRで更新されるので影響は無いが、consoleなどで追っかけているとObserverが動いていてちょっと気持ち悪い

解決方法: Subjectを利用してmodule.hot.disposeで発火して止める

import { combineEpics } from "redux-observable"
import { interval, Subject } from "rxjs"
import { map, takeUntil } from "rxjs/operators"

const disposer = new Subject()

export const timerEpic = () => {
  return interval(1000).pipe(
    takeUntil(disposer), // disposerが動くまでtimerを動かす
    map((time) => ({
      type: "TIMER",
      value: time
    }))
  )
}

if (module.hot) {
  module.hot.dispose((data) => {
    disposer.next()
  })
}

typescriptの場合、module.hot@types/webpack-envに定義されているので入れると良い

HMR部分を分離する

こんな感じにHot Reload関連の部分を切り出しておくのも良いだろう。

// hotReload.ts
import { Subject } from "rxjs"
import { takeUntil } from "rxjs/operators"

const hmrDisposer = new Subject()

export const registerDisposeHandler = (module) => {
  if (module.hot) {
    module.hot.dispose(() => hmrDisposer.next())
  }
}

export const takeUntilHotReload = () => takeUntil(hmrDisposer)

ただしmodule.hotのフックは全てのdependencyのルートであるrootEpicの記述箇所と一緒にしておかないと上手く発火されないので注意

export const rootEpic = combineEpics(pingEpic)

// 全てのepicが更新されたタイミングでdisposeを呼び出すように仕掛ける
registerDisposeHandler(module)
2
2
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
2
2