zalmoxisus/redux-devtools-extension

"Failed to retrieve persisted state from storage" or "Uncaught DataCloneError: Failed to execute 'postMessage' on 'Window': An object could not be cloned."

Closed this issue · 17 comments

Having trouble getting this to work. Here is my setup:

const combinedReducers = compose(
    mergePersistedState()
)(combineReducers({
    router: routerStateReducer,
    ...reducers
}));


const storage = compose(
    filter('user')
)(adapter(window.sessionStorage));

export default compose(
    applyMiddleware(promiseMiddleware),
    persistState(storage, 'workflow'),
    reduxReactRouter({
        createHistory
    }),
    window.devToolsExtension || (f => f)
)(createStore)(combinedReducers);

This gives me:

Uncaught DataCloneError: Failed to execute 'postMessage' on 'Window': An object could not be cloned.

If I insert the DevTools.instrument() in compose (do we need this?) like so:

export default compose(
    applyMiddleware(promiseMiddleware),
    persistState(storage, 'workflow'),
    reduxReactRouter({
        createHistory
    }),
    DevTools.instrument(),
    window.devToolsExtension || (f => f)
)(createStore)(combinedReducers);

I get:

Failed to retrieve persisted state from storage: TypeError: Cannot read property 'state' of undefined

and

Uncaught TypeError: Cannot read property 'state' of undefined

I can get rid of the first error by removing my persistState (redux-localstorage) plugin. But the second error persists.

Hey, @adamscybot. Just released 0.1.0, please sync the git, reload the extension and try again without persistState.

Also you need at least Redux 3.0.0.

No, you don't need DevTools.instrument(), and even don't need to import redux-devtools, the extension does this for you.

persistState is imported from redux-devtools or from redux-persist?

I'm also getting the postMessage error, with the latest build/extension from git.
Full error:

Uncaught DataCloneError: Failed to execute 'postMessage' on 'Window': An object could not be cloned.
  t @ page.bundle.js:8
  (anonymous function) @ createStore.js:52
  dispatch @ createStore.js:50
  p.dispatch @ page.bundle.js:5
  (anonymous function) @ bindActionCreators.js:12
  mouseMove @ group.js:374
  handleEvent @ group.js:104

Using Redux version 3.0.4.
Using the following initialization:

const store = (window.devToolsExtension ? window.devToolsExtension(createStore) : createStore)(appReducer);

So no other store enhancers, like persistState or redux-devtools.

The extension does with with the supplied counter example.

Googling a bit, I found that the exception is caused by the browser's implementation of the structured cloning algorithm, which Window.postMessage uses to clone objects. The implementation of the cloning algorithm causes an error to be thrown when attempting to clone error, function, and DOM node objects.

I've checked, both examples with fine.

I'm in the process of adapting an existing app to Redux, which means I still have some data objects that are instances of a class and THREE.Vector2's.
Is this issue specific for the extension or Redux devtools in general?

I guess it's specific for the extension when we have to send more complex data. Serializing the data should solve it. I'll try to implement this.

Just pushed a new commit, which serialize the data from the page script.

@peteruithoven, could you try it out as indicated here?

It should help with sending the data to the DevTools, but I am also wandering whether we need to serialize the data coming back in case of redoing/undoing actions. But don't want to add unnecessary serializations to not decrease the performance.

Tried it, I'm afraid there is another place that needs to be serialized

Uncaught TypeError: Converting circular structure to JSONonChange @ page.bundle.js:30356
  (anonymous function) @ createStore.js:52
  dispatch @ createStore.js:50
  dispatch @ page.bundle.js:12277
  (anonymous function) @ bindActionCreators.js:12
  mouseUp @ group.js:350
  handleEvent @ group.js:80

Since as you say this impacts performance, it would be good if this was optional. Having error, function, and DOM node objects in Redux state seems bad practice?

So, those data cannot be even passed to JSON.stringify.
Could you add an example to github? So I will be able which data we have to clone.

Or I will try an existing solution: https://github.com/isaacs/json-stringify-safe. Though not sure that the result of this operation will be suitable for DevTools. So it would be better to have an example for testing.

I've tried to make an example. I'm not sure where the problem lies in our store, so I've tried a couple of things, but nothing broke it. So I've added a very basic circular dependency (this.me = this) in a piece of data.
https://github.com/peteruithoven/redux-devtools-extension-issue-example

You can run this by simply starting a webserver in the folder. SystemJS (JSPM) should take care of the rest.

Is it possible to log more debug info, so that I can more easily figure out what in my state causes this?

Actually, we don't need more debug data here. You may even by yourself try to do

JSON.stringify({payload: store.liftedStore.getState()});

and you should get the same error.

Reproduced. Added window.store = store; in your example and the code from my previous message throw the same error. Will look into it.

In my case, I am not knowingly storing anything other than plain object in my store....so I cant explain why it happens in my case. Maybe some middleware I am using temporarily puts something other than a plain object in the stor. Seems possible -- I haven't looked into what redux-promise does for example.

@adamscybot, @peteruithoven, thanks a lot for helping with this! I solved it by using json-stringify-safe, which doesn't throw on circular references instead of JSON.stringify.

Please try it out by running npm i & npm run build:extension and reloading the extension.

As I mention before, I added serialization only for sending data from the page script. So it could be another issue with undoing/redoing action. But till it works, don't want to add unnecessary serializations to not decrease the performance.

Feel free to reopen the issue if something goes wrong.

UPD: Instead of building the extension, you may get it from Chrome WebStore, it should work as well. Please let me know if it does.

It works! Awesome work!
(Installed from the WebStore)