Remove/disconnect epics from redux-observable

670 views Asked by At

We run our integration tests within Node, using enzyme's mount and jsdom to render the full app. For each test, we create a new store

return createStore(
    reducer,
    stateShape,
    composeEnhancers(
        applyMiddleware(epicMiddleware, navMiddleware)
    )
);

Unfortunately, doing this for multiple tests I've noticed that each epic has been attached multiple times, so instead of one epic acting one an action 10 of the same one are! Is there a way I can run cleanup at the end of each test so that the epics are detached and no longer listening?

We're using redux, redux-observable, and enyzme+mocha to test. Thanks!

2

There are 2 answers

0
jayphelps On BEST ANSWER

Every time you create a new store, you'll need to create a new instance of the epicMiddleware that you give it.

Alternatively, there is epicMiddleware.replaceEpic(rootEpic) which lets you replace the currently running root epic, but I'm not sure that will solve your problem in this case.

0
strider On

Since replaceEpic was sun-setted as of redux-observable@1 you'll need to use this approach outlined here w/ BehaviorSubject and switchMap if you're on a later release:

https://redux-observable.js.org/docs/recipes/HotModuleReplacement.html

import { rootEpic, anotherRootEpic } from './where-ever-they-are';
import { BehaviorSubject } from 'rxjs';
import { switchMap } from 'rxjs/operators';

const epicMiddleware = createEpicMiddleware();
const store = createStore(rootReducer, applyMiddleware(epicMiddleware));

const epic$ = new BehaviorSubject(rootEpic);
// Every time a new epic is given to epic$ it
// will unsubscribe from the previous one then
// call and subscribe to the new one because of
// how switchMap works
const hotReloadingEpic = (...args) =>
  epic$.pipe(
    switchMap(epic => epic(...args))
  );

epicMiddleware.run(hotReloadingEpic);

//  this next line swaps the epic
epic$.next(anotherRootEpic);