redux-devtools: Breaking changes after updating extension to v3

After updating the Redux Dev Tools extension (Chrome) to v3 this weekend, our app is no longer working when the extension is enabled. Still works on Firefox as the add on hasn’t been updated yet.

We use redux-most as middleware, like so:

import { createStore, compose, combineReducers } from 'redux'
import { combineEpics, createEpicMiddleware, createStateStreamEnhancer } from 'redux-most'

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const epicMiddleware = createEpicMiddleware(
    combineEpics([
        appEpic,
        ... // other epics here
    ])
)

const store = createStore(
    combineReducers({
        appReducer,
        ... // other reducers here
    }),
    composeEnhancers(createStateStreamEnhancer(epicMiddleware))
)

export default store

And now when accessing state (using withState), instead of the regular state object being returned it looks something like this:

{
    actionsById: {...},  
    committedState: undefined, 
    computedStates: [{...}],
    currentStateIndex: 1,
    isLocked: false,
    isPaused: false,
    monitorState: {},
    nextActionId: 2,
    skippedActionIds: [],  
    stagedActionIds: [0, 1, ...],
}

Where the actual state object can be located at the last index of computedStates

Does anyone have any ideas as to what happened here and how it could be resolved? Thanks

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 3
  • Comments: 34 (15 by maintainers)

Most upvoted comments

@Methuselah96 gotcha. Really appreciate your detective work and digging here!

It worked with 3.0.3. Thanks @Methuselah96 ✌🏻

The issue is: Redux 4.0.5 depends on symbol-observable as does most. symbol-observable polyfills Symbol.observable and so it doesn’t matter which one calls symbol-observable first, because the first one to access will do the polyfill and therefore both libraries will share the same symbol.

Redux 4.1.0 does not depend on symbol-observable and is instead just doing a ponyfill for the observable symbol. Therefore if redux is imported first, it sees that Symbol.observable is not set and decides to use '@@observable' as the ponyfill. However when symbol-observable is imported later, it polyfills Symbol.observable and that is what is used by most. Because of that the ponyfill and polyfill observable symbol properties don’t match up and most crashes because it was expecting the Redux store to have the Symbol.observable polyfill property.

So it seems like Redux should polyfill Symbol.observable if it wants to remain compatibility with libraries that use symbol-observable (perhaps add back the dependency on symbol-observable for simplicity?).

Thanks @Methuselah96 3.0.3 also fixes an issue we were having with accessing the observable manually using symbol-observable. Appreciate the quick turnaround!

  1. Can you try out Redux DevTools - Next as well when you get a chance?

@Methuselah96 Yes it crashed image

react_devtools_backend.js:4045 Unhandled Promise rejection: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. ; Zone: <root> ; Task: Promise.then ; Value: TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    at subscribeTo (subscribeTo.js:27)
    at from (from.js:9)

@Methuselah96 Sure, just installed and it crashed with:

from.js:31 Uncaught TypeError: from(x) must be observable, iterable, or array-like: [object Object]
    at from (from.js:31:1)
    at createStateStreamEnhancer.js:19:47
    at <anonymous>:10606:19
    at createStore (redux.js:154:1)
    at Module../src/redux/store.js (store.js:31:26)
    at __webpack_require__ (bootstrap:79:1)
    at Module../src/index.jsx (index.jsx:1:1)
    at __webpack_require__ (bootstrap:79:1)
    at checkDeferredModules (bootstrap:45:1)
    at bootstrap:152:1

@Methuselah96 i will open something up tomorrow morning if that’s ok! Once again, thank you for all your help tonight! I’ll be back tomorrow!

Thanks for the info. My guess is that the reason it breaks with the extension but not with plain Redux is because the order of import is the Redux DevTools extension, most/RxJS, and then Redux. I have a fix in mind that I’ll try to get out today.

Was the dependency causing any specific problems? It seems like adding a few bytes to the bundle size is easily worth it in this case in order to avoid the special instructions of having to import the polyfill first, any complications that arise from that, as well as any developer time spent trying to figure out why it’s broken. It’s a pretty bad gotcha and easily solved on the Redux side of things. I like getting rid of dependencies as much as the next person, but this one seems like a net positive.