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 · 6 comments

Comments

Projects
None yet
3 participants
@rgommezz

rgommezz commented Jan 18, 2017

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

This comment has been minimized.

Show comment
Hide comment
@zalmoxisus

zalmoxisus Jan 18, 2017

Owner

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.

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

This comment has been minimized.

Show comment
Hide comment
@rgommezz

rgommezz Jan 18, 2017

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 :)

rgommezz commented Jan 18, 2017

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

This comment has been minimized.

Show comment
Hide comment
@zalmoxisus

zalmoxisus Jan 18, 2017

Owner

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.

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

This comment has been minimized.

Show comment
Hide comment
@rgommezz

rgommezz Jan 18, 2017

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!

rgommezz commented Jan 18, 2017

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!

@rgommezz rgommezz closed this Jan 18, 2017

zalmoxisus added a commit that referenced this issue Jan 18, 2017

@zalmoxisus zalmoxisus referenced this issue Jan 24, 2017

Closed

React 16 Umbrella ☂️ (and 15.5) #8854

117 of 120 tasks complete
@joetidee

This comment has been minimized.

Show comment
Hide comment
@joetidee

joetidee 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 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

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment