2
votes

I'm new to Redux-Observable. So, I apply redux-observable in my project, and i want to dispatch action by redux-observable so i used "of" (like Observable.of() in RXJS version before). But the reponse that i received is "Actions must be plain objects. Use custom middleware for async actions". Is there a wrong with my set up epic middleware or code?

store.js

import { createStore, applyMiddleware, compose } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import { rootEpic } from './epics';
import reducers from './reducers';

const epicMiddleWare = createEpicMiddleware();
const configureStore = () => {
  const store = createStore(
    reducers,
    compose(
      applyMiddleware(epicMiddleWare),
      window.devToolsExtension ? window.devToolsExtension() : (f) => { return f; },
    ),
  );

  epicMiddleWare.run(rootEpic);

  return store;
};

export default configureStore;

epic.js

export const fetchNavigationEpic = (action$) => {
  return action$
    .ofType(actionTypes.FETCH_NAVIGATION_LIST)
    .pipe(
      mergeMap(() => {
        return from(CreateService(SettingService).getAll())
          .pipe(
            map((response) => {
              if (response.status === 200) {
                return of(fetchNavigationSuccess(response));
              }

              return fetchNavigationFailed(response);
            }),
          );
      }),
    );
};

action.js

export const fetchNavigation = { type: actionTypes.FETCH_NAVIGATION_LIST };
export const fetchNavigationSuccess = (payload) => {
  return { type: actionTypes.FETCH_NAVIGATION_LIST_SUCCESS, payload };
};
export const fetchNavigationFailed = (payload) => {
  return { type: actionTypes.FETCH_NAVIGATION_LIST_FAILED, payload };
};

Library information: "redux-observable": "^1.0.0", "rxjs": "^6.2.1", "rxjs-compat": "^6.2.1",

1

1 Answers

3
votes

The issue is that you're returning a stream not an action.

If you're return an observable (of(yourAction)), you need to flatten that using mergeMap

If you're return the action, then you can use map instead of mergeMap

So it's either

export const fetchNavigationEpic = (action$) => {
  return action$
    .ofType(actionTypes.FETCH_NAVIGATION_LIST)
    .pipe(
      mergeMap(() => {
        return from(CreateService(SettingService).getAll())
          .pipe(
            mergeMap((response) => {
              if (response.status === 200) {
                return of(fetchNavigationSuccess(response));
              }

              return of(fetchNavigationFailed(response));
            }),
          );
      }),
    );
};

Or

export const fetchNavigationEpic = (action$) => {
      return action$
        .ofType(actionTypes.FETCH_NAVIGATION_LIST)
        .pipe(
          mergeMap(() => {
            return from(CreateService(SettingService).getAll())
              .pipe(
                map((response) => {
                  if (response.status === 200) {
                    return fetchNavigationSuccess(response);
                  }

                  return fetchNavigationFailed(response);
                }),
              );
          }),
        );
    };