Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: Cannot convert undefined or null to object #250

Closed
ValeryVS opened this issue Aug 8, 2017 · 20 comments · Fixed by #254
Closed

Error: Cannot convert undefined or null to object #250

ValeryVS opened this issue Aug 8, 2017 · 20 comments · Fixed by #254

Comments

@ValeryVS
Copy link

ValeryVS commented Aug 8, 2017

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

What is the current behavior?

With AOT build Error Cannot convert undefined or null to object is thrown at this line

const reducerKeys = Object.keys(reducers);

because reducers is null.

  const reducerKeys = Object.keys(reducers);

Expected behavior:

I'm injecting reducers as described here
https://github.com/ngrx/platform/blob/master/docs/store/api.md#injecting-reducers

Minimal reproduction of the problem with instructions:

https://github.com/ValeryVS/angular-storage-experiment/blob/02fd926e17547abfdb213b3d8dd3af3392218238/src/app/store/reducer.ts
Same error has been reproduced there.
I can update repo to match instruction above.

Version of affected browser(s),operating system(s), npm, node and ngrx:

$ node -v
v6.11.1
$ npm -v
3.10.10

@ngrx/store@4.0.2

Other information:

@ValeryVS
Copy link
Author

ValeryVS commented Aug 8, 2017

Possible relative #175

@Christian24
Copy link

I have the same issue. I am on Typescript 2.4.2. Disabling AOT fixes the issue. My getReducers function is not executed (I added a console.log).

@ValeryVS
Copy link
Author

ValeryVS commented Aug 9, 2017

Right, I also tried to debug this a while, and found that reducers factory is not executed.

@Christian24
Copy link

Wouldn't that mean it is more a CLI issue though? AOT is only active in production mode right? Because everything works as expected in development mode.

@ValeryVS
Copy link
Author

ValeryVS commented Aug 9, 2017

@Christian24
Well... it can be issue with ngrx/store or documentation or with angular itself. Don't think that CLI is relative here.
You can ng build --prod --aot=false to make production build without though.

@Christian24
Copy link

@ValeryVS true. I have tried that. When disabling AOT it works, but I would hate to give up AOT.

@brandonroberts
Copy link
Member

I have a fix for this that will work for JiT/AoT. It should land soon once I submit the PR

@Christian24
Copy link

While the error goes away, my reducer still is not called. I detailed this in #189

@tschuege
Copy link

tschuege commented Aug 22, 2017

@ValeryVS @Christian24 @brandonroberts
I have the same issue.

  • Angular 4.3.5
  • @ngrx/store@4.0.3

It works on the first load (empty cache and hard reload), but after that when doing a normal reload, it get: Uncaught TypeError: Cannot convert undefined or null to object at Function.keys ()

I tried various approaches like #189 but non of them worked.

Were you able to solve it? And if yes, how?

@manojc
Copy link

manojc commented Dec 21, 2017

I am getting the same error and I'm not sure if it's a problem of ngrx or if it's fixed yet.

I tried using #254 fix but it doesn't seem to work.

It works perfectly fine if I build the application using JIT strategy.

It fails when I use AOT strategy using ng build --aot --watch --extract-css false --output-hashing none command.

I tried to debug the problem and found that combineReducers function in store.es5.js gets fired twice (unlike in JIT where it gets fired only once) which I didn't understand.
The reducers parameter of this function is null in second call and hence it throws the error.

I have got a couple of screenshots for further details.

Console Error

aot-error-console-error

store.es5.js file

aot-error-store es5 js

Please let me know if I am missing something. Thanks.

@FredericGryspeerdt
Copy link

Any updates on this? I've encountered the same error ...

@kristof01
Copy link

kristof01 commented Mar 13, 2018

I had the same issue.
I was able to solve it by declaring the getReducers function in my feature module's module.ts file, instead of declaring it in the reducer's index.ts file.

@David-Mueller
Copy link

FYI the problem was, that angular AOT does not work with default exports (at least for reducers).
I fixed my problem by refactoring all reducer default exports to named exports.

@blong824
Copy link

@David-Mueller , can you show an example of this please?

@timdeschryver
Copy link
Member

export default function (....) { 
  ...
}

becomes

export function reducer (...) {
 ...
}

@blong824
Copy link

Well I don't have export default function anywhere in my code. I am using my own Angular 6 library in my app. Everything compiles and runs with ng serve. When I build for production it compiles but when I try and run it locally I get the error mentioned above. I tried with --aot=true and --aot=false

@David-Mueller
Copy link

Hi,
unfortunately, this fixed it for me.

I'd double check, if all of the reducer imports are fine or if I pass undefined as a reducer somewhere with aot enabled.
Good luck

@mcoomans
Copy link

mcoomans commented Oct 4, 2018

I have struggled with the same issue. I managed to solve it by declaring a wrapper for the reducer function right inside the module.ts file, similar to @kristof01 's suggestion above.

Original failing code

@NgModule({
  imports: [
    StoreModule.forFeature(
      'feature', featureNs.reducers 
    ),     ...
  ],`

( featureNs is a namespace and reducers is an ActionReducerMap.) Works with a JIT build, not an AOT build.

I got the AOT build working with (all in the module.ts file):

const combinedReducer: ActionReducer<featureNs.state, Action> =
   combineReducers(featureNs.reducers);

export function reducerWrapper(
  state: featureNs.state, action: Action): featureNs.state {
  return combinedReducer(state, action);
}

@NgModule({
  imports: [
    StoreModule.forFeature(
      'feature', reducerWrapper 
    ),     ...
  ],`

Note: the above module was part of an Angular feature Library (build with ng-packagr), and then imported in an app build with the AOT compiler. Not sure if the library part makes any difference...

@prabhatojha
Copy link

prabhatojha commented Dec 20, 2019

Things were working perfectly in DEV mode, then it became a nightmare when I deployed my application to production with the AOT flag on. It took me 2 days to figure out the solution for my specific case.

So I was using Object.assign to combine all my reducers.

Before
export const AppReducers = Object.assign({ APP_REDUCER: AppReducer }, OtherReducers );

After
export const AppReducers = { APP_REDUCER: AppReducer, ...OtherReducers } );

After a lot of hit and trial, I just removed the Object.assign and used spread operator, tadda, everything is working fine with and without the AOT flag. Surprising.

But I really want to understand why Object.assign wasted my 2 days? if anyone can put some lights on it?

@AliF50
Copy link

AliF50 commented Feb 3, 2021

@mcoomans Thanks for your comment. I was facing the same issue and without your comment I wouldn't be able to solve it. Your way in the comment fixes it but there is also a different way.

Doing it like the 2nd snippet here fixes it too. (https://github.com/ngrx/platform/blob/v5.2.0/docs/store/api.md#injecting-reducers)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.