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

Reducer misfiring, undetected by extension #326

Open
funwithtriangles opened this issue Mar 23, 2017 · 10 comments
Open

Reducer misfiring, undetected by extension #326

funwithtriangles opened this issue Mar 23, 2017 · 10 comments

Comments

@funwithtriangles
Copy link

My app has a bug that doesn't happen when redux-devtools-extension is disabled. One of my reducers is dealing with an action twice, that has only been dispatched once. I can outline the situation:

  1. Land on page FOO
  2. Action A fires as expected (seen in log)
  3. State updates as expected
  4. Move to page BAR
  5. State mutates, as if action A was fired again. (however, action A is not seen in log this time)

Action A cannot be seen in the log a second time, but if I console log inside the reducer, I see the reducer is indeed experiencing the action twice. Checking where the action is being dispatched from, this only happens once.

I realise this is a vague explanation but I'm just wondering if there have been any similarly known issues like this? I've tried a number of things (latency, serialize) to no avail.

@zalmoxisus
Copy link
Owner

Whenever you invoke replaceReducer, Redux Devtools enhancer recomputes the reducers. Try to disable hot reloading to see if that's the issue.

@funwithtriangles
Copy link
Author

funwithtriangles commented Mar 23, 2017

It sure has something to do with replaceReducer. Unfortunately shouldHotReload breaks it in a different way.

I can stop the bug from happening by not replacing my reducers in for code splitting reasons, which might be an acceptable workaround for now.

@zalmoxisus
Copy link
Owner

@funwithtriangles setting shouldHotReload to false doesn't help? It should prevent recomputing.

@funwithtriangles
Copy link
Author

funwithtriangles commented Mar 23, 2017

Looking into it a bit further, setting shouldHotReload to false helps but it now means I'm having to check that the store slice exists in certain parts of my code, presumably because it's not injecting in the same way as before? I can't say I quite understand what's going on!

I feel that there's always going to be some sort of price to pay in order to use redux-dev-tools and replaceReducer?

@zalmoxisus
Copy link
Owner

Well, initially replaceReducer was intended to be used for Redux DevTools only as signal that the root reducer was hot-reloaded, but it's rather useful for code splitting as well.

When disabling this feature (setting shouldHotReload to false), DevTools enhancer will not recompute the history when you change something in the reducers, but the new actions will work as expected. Usually, it's not a big price.

@funwithtriangles
Copy link
Author

funwithtriangles commented Mar 23, 2017

Unfortunately I'm getting errors like this:

Uncaught TypeError: Cannot read property 'accounts' of undefined

undefined being the new part of the store that has just been added via replaceReducer. Is this not expected? This error doesn't happen when the extension is disabled in Chrome.

@zalmoxisus
Copy link
Owner

zalmoxisus commented Mar 23, 2017

Seems that there are edge cases indeed. I'll add some tests to see what is happening in this case. If you can add a test to reproduce it here, it would be much appreciated.

@funwithtriangles
Copy link
Author

@zalmoxisus thanks a bunch for looking into this! I've had a look at those tests and I'm not sure if my knowledge in the whole area is strong enough to be successful reproducing the issue.

@funwithtriangles
Copy link
Author

funwithtriangles commented Mar 24, 2017

I've spent a bit more time looking into this, shouldHotReload set to false works as you explained but I'm having what seems to be an async/latency issue. Replacing the reducer doesn't seem to happen synchronously...

 injectReducer(store, { key: 'transactions', reducer })

 console.log(store.getState().transactions) // undefined

 setTimeout(() => {
    console.log(store.getState().transactions) // yay we have stuff!
  }, 100)

And here's the code for injectReducer:

export const injectReducer = (store, { key, reducer }) => {
  if (Object.hasOwnProperty.call(store.asyncReducers, key)) return

  store.asyncReducers[key] = reducer
  store.replaceReducer(makeRootReducer(store.asyncReducers))
}

Is this async type behaviour something to do with latency coming from the devtools? I've tried latency set to 0 but that didn't help. makeRootReducer makes use of combineReducers, but as far as I'm aware all of the code is synchronous...

@zalmoxisus
Copy link
Owner

I'm sorry for the delay on this issue. I just published version 2.15.0 of the extension which addresses this as implemented in zalmoxisus/redux-devtools-instrument@5a69cce.

If setting shouldHotReload to false still doesn't help, please modify the tests here.

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

2 participants