return EMPTY crash my redux observable chain
Asked Answered
P

2

6

I am using redux, redux-observable.

I have the following

import { EMPTY, Observable } from "rxjs";

const setCurrentDatastoreIdEpic = (action$, state$): Observable<any> => action$.pipe(
    ofType(DatastoreActions.setCurrentDatastoreId),
    map((action: {payload: {datastoreId: string}}) => {
        if(action.payload.datastoreId) {
            return ItemsActions.getItemsListRequest({
                datastoreId: action.payload.datastoreId,
                page: 1,
            });
        } else {
            return EMPTY;
        }
    })
);

But everytime I go in the else I have

Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.

But they say to use EMPTY if there is no action dispatched.

I also tried Observable.empty() but it say that empty do not exist in Observable (and this way is deprecated from what I saw)

Peugia answered 4/12, 2019 at 7:40 Comment(0)
B
5

The problem is that you're using operator map and inside that you're returning EMPTY. EMPTY is an Observable that emits no next notification and emits just one complete notification. But map doesn't care what you return from its projection functions so it takes EMPTY and passes it further where redux-observable complains because EMPTY is not an action.

So instead of map you can use concatMap (or mergeMap would work as well) and wrap ItemsActions.getItemsListRequest with of(). Returning EMPTY into concatMap is perfectly correct.

concatMap((action: {payload: {datastoreId: string}}) => {
    if(action.payload.datastoreId) {
        return of(ItemsActions.getItemsListRequest({
            datastoreId: action.payload.datastoreId,
            page: 1,
        }));
    } else {
        return EMPTY;
    }
})
Bhutan answered 4/12, 2019 at 9:53 Comment(3)
Thanks for the explenation, what about if I return something like this ? return ({ type: 'NO DATASTORE SELECTED'}) It does work, but is it a good practice ?Peugia
If you have an epic that is 'read-only' (e.g. you do not want to return an action from it), you can return ignoreElements(), which is like returning an empty observable, but is the approach recommended by the official docs.Dethrone
This epic conditionaly doesn't return anything. ignoreElements() will ignore always everything.Bhutan
A
0

in addition to this if you just want some action epic do nothing with the store you can use ignoreElements() instead of map

Ambroid answered 31/7, 2021 at 6:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.