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

Cannot read property 'getIn' of undefined #20

Open
venil7 opened this issue Feb 1, 2016 · 34 comments
Open

Cannot read property 'getIn' of undefined #20

venil7 opened this issue Feb 1, 2016 · 34 comments

Comments

@venil7
Copy link

venil7 commented Feb 1, 2016

I'm getting error when rendering

<OAuthSignInButton
          provider=...
          endpoint=... />

I'm specifying both required provider and endpoint props, but I get this error:

Uncaught TypeError: Cannot read property 'getIn' of undefined

@julius-retzer
Copy link

I have the same issue

@josmardias
Copy link

@venil7 and @Wormyy, do you have a reproduction for us?

@jadehopepunk
Copy link

I got the same error, which seemed to be caused by not having the reducer specified

import {authStateReducer} from "redux-auth";
// create your main reducer
const reducer = combineReducers({
  auth: authStateReducer,
  // ... add your own reducers here
});

It'd be nice if it handled this a bit better, either handling the null value, or returning an error telling people what to do. Also, the instructions in the README don't mention setting up the reducer. The example app certainly has it in there, but it also has a lot of other stuff that a real app doesn't need.

@nyjy85
Copy link

nyjy85 commented Apr 4, 2016

If you use 'combineReducers' from 'redux-immutable' as opposed to 'redux', it will throw that error because, in order to get the 'auth' state, it needs to be retrieved via 'store.getState().get('auth')' as opposed to 'store.getState().auth', since it is now an immutable. How is it possible to work around this? I am using redux-immutable for combineReducers and would like to keep it this way.

@hhhonzik
Copy link
Contributor

Hey @nyjy85,

I came across the same issue and there is a problem with initialState being undefined or plain object.

You can just wrap authStateReducer with initial immutable state like this:

import { authStateReducer } from "redux-auth";
import Immutable from "immutable";

const auth = (state = {}, action) => {
  return authStateReducer(Immutable.fromJS(state), action);
}

const appReducer = combineReducers({
  auth,
  ...
});

@dpereira411
Copy link

I'm getting the same error but probably on a different place (a promise?)
Uncaught (in promise) TypeError: Cannot read p roperty 'getIn' of undefined(…)

This happens as soon as I render <EmailSignInForm />.
I'm using combineReducers from redux-immutable and wrapped the reducer with @hhhonzik code.
I'm also using the library in a client-only architecture so that could be the problem? (regarding #7)

@yury-dymov
Copy link

@dpereira411, have you added AuthGlobals component to your root template? Have you executed configure from 'redux-auth'?

@arjshiv
Copy link

arjshiv commented Jul 19, 2016

I'm having this issue too, even after setting up AuthGlobals, the reducer and executing configure

@Fr33maan
Copy link

@lynndylanhurley Hey maybe time to do something, people can't use your module :)

@lynndylanhurley
Copy link
Owner

@L1br3 - write me a failing test and I'll fix it.

@Fr33maan
Copy link

Sorry @lynndylanhurley but I definitely stoped using your module as I couldn't make it work because of this error. I just alarm you on the importance of this blocking problem.
So I won't take the time to write a test, sorry again.

@lynndylanhurley
Copy link
Owner

I cannot reproduce this issue. That may be because it's been fixed in one of the latest releases, or because your environments are different than mine. So I'm going to close this issue out.

Anyone, feel free to re-open the issue (or create a duplicate) if you can provide a failing test, or if you can explain how your environment is different from the working demo app and how that difference is causing problems.

@arjshiv
Copy link

arjshiv commented Jul 20, 2016

@lynndylanhurley If it helps at all, I was trying to implement this in a https://github.com/mxstbr/react-boilerplate/tree/master/app boilerplate app, after including thunk and making sure that everything in the config notes was followed. I can write up an example repo and point you to it later today if that helps. My main suspicion is that since the react boilerplate uses sagas instead of thunk, maybe having them both is confusing the app ?

@lynndylanhurley
Copy link
Owner

Thanks @arjshiv, that may be the case.

@arjshiv
Copy link

arjshiv commented Jul 20, 2016

No worries, I'll have a test repo up and hopefully you can help me debug. BTW, I love what you've done, and I have my fingers crossed that I'll be able to use it once we get past this :)

@arjshiv
Copy link

arjshiv commented Jul 20, 2016

@lynndylanhurley Please check out this commit to see what I had:

arjshiv/redux-auth-test@dab0355

You'll need to run npm install and then npm start and it should open up the app at localhost:3000

You'll need to uncomment the line in https://github.com/arjshiv/redux-auth-test/blob/dab0355965705d78e7ff812bf6358dc5620e6e89/app/containers/HomePage/index.js to see the exact issue replicated

@arjshiv
Copy link

arjshiv commented Jul 20, 2016

For more context, this is on MacOS

@lynndylanhurley
Copy link
Owner

@arjshiv - thanks for sending that detailed example.

@nyjy85 was right - the problem is that the redux-auth components expect there to be a normal javascript object called auth at the root level of your store. Her comment above explains the problem you're having.

In your application, the entire store is an Immutable.js Map, and the redux-auth components don't know how to read that.

I'll try to include a fix this for the next release, but it will be a bit of work and I'm not sure when it will be ready by.

It looks like you've included @hhhonzik's workaround:

const auth = (state = {}, action) => { //otherwise this reducer doesn't work with redux-immutable
  return authStateReducer(Immutable.fromJS(state), action);
};

But it doesn't seem to be solving the problem.

@hhhonzik - was there anything else you needed to do to work past this issue?

@arjshiv
Copy link

arjshiv commented Jul 21, 2016

@lynndylanhurley Thanks for taking a look. The most immediate workaround I can think of is not to use Immutable in the app and use something like seamless-immutable instead (or just plain Object.assign to make an 'immutable' state), but that will not scale for your framework since most people building larger apps that require authentication are moving towards using Immutablestates. @hhhonzik Any tips you have would also be greatly appreciated!

@arjshiv
Copy link

arjshiv commented Jul 26, 2016

Hey guys, any updates on this ? @lynndylanhurley

@lynndylanhurley
Copy link
Owner

@arjshiv - I'll need to provide a configuration option for accessing the auth reducer store from the root store. I'm super busy with work but hopefully I'll have this ready by next Monday or so.

@arjshiv
Copy link

arjshiv commented Jul 26, 2016

No worries, appreciate the help!

On Tue, Jul 26, 2016 at 11:33 AM Lynn Dylan Hurley notifications@github.com
wrote:

@arjshiv https://github.com/arjshiv - I'll need to provide a
configuration option for accessing the auth reducer store from the root
store. I'm super busy with work but hopefully I'll have this ready by next
Monday or so.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#20 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AB6FO_iD0Be0Y-auAJQ5rwqZGiUuaycXks5qZijkgaJpZM4HQbq-
.

@tomascharad
Copy link

tomascharad commented Aug 8, 2016

Hi all,

+1 on the redux-immutable problem.

I also tried the workaround but it doesn't work as combineReducers creates an immutable object which is passed to the connect function.
When connect tries to do:

export default connect(({auth}) => ({auth}))(AuthGlobals);

It breaks, since the param given to connect is not a plain object.

this could be solved by changing the selector to something like:

(state) = > {
  let auth = state.auth;
  if (!auth) {
    auth = state.get('auth')
  }
  return auth;
}

Would this approach be approved if I submit a PR?

@tomascharad
Copy link

tomascharad commented Aug 8, 2016

Hi @lynndylanhurley ,

I just hardcoded every container of redux-auth so it access the auth state like this:

export default connect((state) => ({ auth: state.get('auth') }))

And is working, I believe that if we isolate the selector in a module so it handles the immutable case (like in my previous post) for the meanwhile, then we could further give the users the ability to customize this selector.
If you guide me a bit I could help you with a PR.

@jimbofreedman
Copy link

Is anyone still thinking about this? I've hit the same issue and would rather pick up where you left off than start from scratch :)

@tomascharad
Copy link

@jimbofreedman, By the meantime I think you could fork the repo and do what I did on my last comment.

@luisguilhermemsalmeida
Copy link

luisguilhermemsalmeida commented Sep 10, 2016

@jimbofreedman I did what you told to do, and I could get it working, but after including AuthGlobals I got the same error from before (connect.js:154 Uncaught (in promise) TypeError: Cannot read property 'getIn' of undefined(…)). Where did you include the AuthGlobals in your project? (using react-boilerplate)

EDIT: Ooops, my bad, I forgot to update TokenBridge.js
from:
export default connect(({auth}) => {

to:
(export default connect((state) => {
let auth = state.get('auth');

@alukach
Copy link

alukach commented Dec 9, 2016

I was bumping into this issue. My problem was that I was using redux-persist, which includes autoRehydrate() middleware that returns a POJO rather than an Immutable.js Map.

@MrHash
Copy link

MrHash commented Dec 14, 2016

Same problem as @alukach integrating with redux-persist. Any suggestions?

@alukach
Copy link

alukach commented Dec 14, 2016

@MrHash I believe someone finishing the PR from #62 would do the trick.

Also, I think you could lean on the createTransform function from redux-persist to convert anything stored in localstorage to a Map object. I haven't had a chance to try this, but I believe this type of thing is what the function was intended for. Something like:

persistStore(store, { transforms: [ createTransform(
    (state) => state.toJS(),
    (state) => Immutable. fromJS(state)
  )
] })

Let me know what ends up working for you.

@KirillSuhodolov
Copy link

Hey @lynndylanhurley any news with fixing this issues or removing useless immutable.js dependency?

@OriaLogic
Copy link

Hi,

I have the same issue, which I could fix when server rendering by adding the following:
Object.defineProperty(store.getState(), 'auth', { get: function() { return this.get('auth'); } });
before injecting the store to the Provider component.

It fixes the issue when server side rendering because now you can access the auth property of the store state by doing state.auth.

The problem on the client side comes (I think) from the fact that the state being immutable, the state object is overwritten every time the state changes, so the defined getter does not exist anymore.

One solution would be to patch redux-immutable to redefine the auth property every time the state changes. What do you think of that? Is it possible? I am currently searching how to achieve that in the redux-immutable library.

Another solution that would come from redux-auth library would be to add named export to every component module and let the developper declare how to connect to the store himself, that is by doing as previously proposed:
export default connect((state) => ({ auth: state.get('auth') }))

Any thought on the above solutions?
I think the second one is pretty easy to implement.

Thanks in advance,
Cheers

@OriaLogic
Copy link

Just to update on my previous comment:
I finally found a solution that works both for server-side rendering and client side. I wrapped my combined reducer with a new reducer function as follows:

const reducer = createReducer();

const reduxAuthPatchedReducer = (state, action) => {
  const returnedState = reducer(state, action)
  Object.defineProperty(returnedState, 'auth', { get: function() { return this.get('auth'); } });
  return returnedState;
}

It is not very nice but it solves the problem and I don't see any side effect so far.
Don't hesitate to tell me if you see an issue with this solution.

hsinhoyeh added a commit to hsinhoyeh/redux-auth that referenced this issue Jun 13, 2017
@mikeover
Copy link

I know this was a year ago, but could you expand on this @OriaLogic ? Could you provide the context of where you're creating your store and reducer? I can't seem to get it working.

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

No branches or pull requests