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

Redux chrome devtools crashing if bound action creator is not wrapped in another function #287

Closed
rgommezz opened this issue Jan 18, 2017 · 8 comments

Comments

@rgommezz
Copy link

I came across a strange issue while dispatching actions that have no payload when I have the chrome devtools enabled.

The below code won't work with devtools-enabled in the store:

Store creation

import { createStore, combineReducers } from 'redux';
import dummyReducer from '../ducks/dummy';

const reducers = combineReducers({
  dummy: dummyReducer,
});

const store = createStore(
  reducers,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

Dummy duck

import { createAction, handleActions } from 'redux-actions';

// Actions
const DUMMY_TOGGLE = 'glen-checkout/DUMMY_TOGGLE';

// Reducer
const initalState = {
  isDummy: false,
};

export default handleActions({
  [DUMMY_TOGGLE]: state => ({ isDummy: !state.isDummy }),
}, initalState);

// Action Creators
export const toggleDummy = createAction(DUMMY_TOGGLE);

Dummy Connected component

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { toggleDummy } from '../ducks/dummy';

const DummyComp = ({ isDummy, onToggleDummy }) => (
  <div style={{ marginTop: 30 }}>
    <button style={{ marginRight: 30 }} onClick={onToggleDummy}>Toggle</button>
    <span>{isDummy ? 'Oh ma\'h, I am a dummy component! 🐗 ' : 'I am a clever component 🤓 '}</span>
  </div>
);

DummyComp.propTypes = {
  isDummy: PropTypes.bool.isRequired,
  onToggleDummy: PropTypes.func.isRequired,
};

export default connect(
  state => ({
    isDummy: state.dummy.isDummy,
  }),
  {
    onToggleDummy: toggleDummy,
  }
)(DummyComp);

This component won't be able to dispatch an action if I set onClick={onToggleDummy}. The console reports the below error when I click on the toggle button:

image

However if I disable devtools in the store, everything works fine.

That problem can be worked around by wrapping the onClick handler in a extra function:
onClick={() => onToggleDummy()}

Any ideas why this could be happening?

@zalmoxisus
Copy link
Owner

zalmoxisus commented Jan 18, 2017

Thanks for the detailed report.

I didn't use redux-actions, but, as far as I understand, it uses any arguments you pass as action payloads. So, in your first case you are passing the event as an action payload, which fails to be stringified (before sending and showing the action object). In the second case, wrapping it in a function, you pass no arguments and it works as expected.

Could you please share a repo or a jsfiddle? So we could reproduce the error and maybe find a way to exclude the events while stringifing.

@rgommezz
Copy link
Author

Aha, that makes sense!
I created a jsfiddle so that you can take a look: https://jsfiddle.net/rauliyohmc/stv9n4f4/2/

Thanks for your hard work on maintaining this amazing library :)

@zalmoxisus
Copy link
Owner

zalmoxisus commented Jan 18, 2017

I don't seem to reproduce the issue with failing to access toISOString.

However, accessing the synthetic event will still not be possible as described in #275. As we are not allowed to access the object properties without throwing an Error by React (in dev mode only), we cannot detect if this object is an event. So, the only solution to prevent this, would be to check if it's an instance of SyntheticEvent like so:

import SyntheticEvent from 'react/lib/SyntheticEvent';
// ...

const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
  serialize: {
    replacer: (key, value) => {
      if (value && value instanceof SyntheticEvent) return '[Event]';
      return value;
    }
  }
}));

Let me know if this approach works for you.

@rgommezz
Copy link
Author

Works like a charm! 👍

Sorry I left the fiddle with the onClick handler wrapped, so no error in that case, otherwise it reports the same error, but a bit masked, due to jsfiddle CORS issues.

Thanks very much for the trick!

@joetidee
Copy link

joetidee commented Apr 14, 2017

I added import SyntheticEvent from 'react/lib/SyntheticEvent'; to my code and my application is throwing this error:

Module not found: Error: Can't resolve 'react/lib/SyntheticEvent' in '/tidee/au/client/src/store'

I'm using React v15.4.1 and if I check the node_modules/react/lib folder the SyntheticEvent.js file does not exist.

@joetidee
Copy link

Ok, just read up on this and the SyntheticEvent solution can no longer be used. Try this instead:

https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/Troubleshooting.md#it-fails-to-serialize-data-when-passing-synthetic-events-or-calling-an-action-directly-with-redux-actions

@tuncatunc
Copy link

Playing audio in react requires storing reference to audio reference in state.
If Audio object is stored in redux store, redux-devtools crashed.
<Audio ref={(audioRef) => setAudioAction(audioRef)}/>

Modified above code snipped as

const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
  serialize: {
    replacer: (key, value) => {
      if (value && value instanceof Audio) return '[Audio]';
      return value;
    }
  }
}));

And redux-devtools is no longer crashes.

@keeth
Copy link
Contributor

keeth commented Feb 6, 2019

I do a duck typing version of the SyntheticEvent check as follows. I guess I am digging into the internals a bit here, but I don't use dev tools in prod, so it only affects developer experience.

serialize: {
  replacer: (key, value) =>
    value && value.dispatchConfig && value._targetInst
      ? '[EVENT]'
      : value,
},

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

5 participants