NgRx chained effects are not fired with webpack


#1

Chaining effects never works with webpack. Here I have built a simple example where a number increments from 0 to 1 then after a delay decrements from 1 to 0.

The INCREMENT effect in home/home.effects.ts dispatches DecrementAction after a delay. At this point the reducer works as expected but the effect is never fired, not seeing the log at all (issue reproduced only with webpack, works as expected otherwise).

Does anyone have idea what could be the problem and possible solution?


#2

@PaulHalliday I hope you could be right person to answer this. It will be great if you find few mins to take a look at the example and share your inputs.


#3

We need a webpack guru in here :slight_smile: - @sean-perkins could you give us a boost here?


#4

All of the @ngrx/ imports are wrong in the playground. They are for some reason showing as ../@ngrx/effects, etc.

For your reducers, you need to cast how to assign, since the web api vs. native api is different.

return Object.assign({}, state, {
     value: state.value + 1
});

#5

@sean-perkins I purposefully imported as ../@ngrx/effects, not only that always I had to use relative path. Otherwise it always throws typescript error while preview.


#6

@sean-perkins Also the NPM packages doesn’t retain when retrieving saved / shared url. As you see in the screenshot below, it still throws error when I import it as @ngrx/store.

@ngrx/store is dependency for @ngrx/effects, again it is not automatically installed or not picked at runtime. I had to manually edit the import path of store as relative, inside effects package when I got it working yesterday.

None of these are issues when using it in a local app, using right import paths as usual but still effect never gets fired with webpack.


#7

@sean-perkins Object.assign instead of spread operator worked. Besides, does this mean spread operator has issues with webpack / nativescript?


#8

So the actual spread operator used for merging arrays (using ...) is webpack safe, as it transpiles down to es5 and uses the raw method of reassigning values.

The issue with using {} like you were using, is the actual Object class on the JS engine used by both Android and iOS devices appears to not share the same API 100% of Web browsers. Object.assign is safe against all implementations and I would highly recommend using it anywhere you are subscribing to value changes of a modified object (mostly in reducers).


#9

Thanks a lot for taking time to explain here.

I tried to debug further with try/catch, actually inside reducers it throws an exception ReferenceError: Can't find variable: __assign. It was defined only inside vendor.js not in bundle.js. Does this give you anything? Could this be a webpack’s issue while bundling?

A quick solution that also allows me to still use spread (...) with Object ({}) is to follow the same procedure explained here for async/await

helper.js

global.__assign = (this && this.__assign) || Object.assign || function (t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
}; 

Or simply global.__assign = Object.assign should also work.