Setting Up Redux Observable

If you are adding redux observable to a new redux project, the first step is to install it along with RXJS

npm i redux-observable rxjs

The next step is to set up the middleware.

Create a middleware and pass it to the createStore function from Redux. Then you create a root epic that combines all your epics and call epicMiddleware.run() with the rootEpic.

import { createStore, compose, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import { combineEpics } from 'redux-observable';
import  { epicA } from './epicA';
import  { epicB } from './epicB';

export const rootEpic = combineEpics(
  epicA,
  epicB
);

const epicMiddleware = createEpicMiddleware();

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default function configureStore() {
  const store = createStore(
    rootReducer,
    composeEnhancers(
        applyMiddleware(epicMiddleware)
    )
  );

  epicMiddleware.run(rootEpic);

  return store;
}

If you are using redux Tooljit then you can replace the configureStore function with:

import { configureStore } from '@reduxjs/toolkit';

export default configureStore( {reducer: rootReducer, middleware: [epicMiddleware] } );

epicMiddleware.run(rootEpic);

export default configureStore( {reducer: rootReducer, middleware: [epicMiddleware] } );

epicMiddleware.run(rootEpic);


Now any epic you create will fire as soon as the app boots.

To call epics on demand, you filter then out of the action stream using `ofType`. So if you want to trigger the following epic then fire an action named `example/epicA`.

import {ofType} from “redux-observable”;

export const someEpic = action$ => action$.pipe(
ofType(‘example/epicA’),
delay(1000),
mapTo({ type: ‘example/epicB’ })
);


The last thing to consider is adding a global error handler to the root epic to catch bugs.

const rootEpic = (action$, store$, dependencies) =>
combineEpics(…epics)(action$, store$, dependencies).pipe(
catchError((error, source) => {
console.error(error);
return source;
})
);


# Resources
- [The official docs](https://redux-observable.js.org/docs/basics/SettingUpTheMiddleware.html) on setting up middleware.
- Redux now recommends writing actions as `domain/eventName` rather than `SCREAMING_SNAKE_CASE`. Don't believe me? [here you go](https://redux.js.org/style-guide/style-guide#write-action-types-as-domain-eventname).


Example Final Store.js for redux toolkit boilerplate

import { configureStore } from ‘@reduxjs/toolkit’;
import counterReducer from ‘../features/counter/counterSlice’;
import { createEpicMiddleware } from ‘redux-observable’;
import { combineEpics } from ‘redux-observable’;
import { combineReducers } from ‘redux’;
import { counterEpic } from ‘../features/counter/counterEpic’;
import {catchError} from ‘rxjs/operators’

export const epics = [
counterEpic
]

export const rootEpic = (action$, store$, dependencies) =>
combineEpics(…epics)(action$).pipe(
catchError((error, source) => {
console.error(error);
return source;
})
);

export const rootReducer = combineReducers({
counter: counterReducer
});

const epicMiddleware = createEpicMiddleware();

export default configureStore( {reducer: rootReducer, middleware: [epicMiddleware] } );

epicMiddleware.run(rootEpic);

 
1
Kudos
 
1
Kudos

Now read this

Trusting your LLM-as-a-Judge

The problem with using LLM Judges is that it’s hard to trust them. If an LLM judge rates your output as “clear”, how do you know what it means by clear? How clear is clear for an LLM? What kinds of things does it let slide? or how... Continue →