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

Dropped Actions? #208

Closed
mAAdhaTTah opened this issue Sep 7, 2016 · 20 comments
Closed

Dropped Actions? #208

mAAdhaTTah opened this issue Sep 7, 2016 · 20 comments

Comments

@mAAdhaTTah
Copy link

I'm working on an app, and there is a point whereby 3 or 4 actions are dispatched fairly quickly, and I'm not seeing them appear in the devtools. I've verified every which way that they are actually being dispatched into the store, but they're not showing up . Have there been any reports of actions being "dropped" this way?

@zalmoxisus
Copy link
Owner

Thanks for the report. I'm also dispatching multiple actions simultaneously in my apps and have no problems with that.

If there are lots of actions and only the first of them are missing, you should increase Limit the action history to on the Settings (Options) page.

If that's not the problem please provide a minimal repo or jsfiddle to reproduce the issue.

@mAAdhaTTah
Copy link
Author

Not so many that it hits the limit. There are four dispatched basically simultaneously and it doesn't seem to be appearing in the devtools. Then there are four more later, of which one or two are showing up. The state appears the be changing in response to the actions though, so I'm not sure where the bug is just yet. If I'm the only one experiencing it, it's probably me, but I'll keep investigating and see if I can repro.

Thanks for your help. Will close when I track it down.

@zalmoxisus
Copy link
Owner

zalmoxisus commented Sep 8, 2016

Usually an action doesn't appear in the monitor logs because the state is mutated somewhere. It can be checked by adding adding redux-immutable-state-invariant middleware. Not sure that's the issue.

Also make sure, you don't filter actions (added action types on the Options page or with actionsBlacklist parameter).

@mAAdhaTTah
Copy link
Author

Is it possible that, if the payload is not serializable, the action would get missed? The objects attached to the dropped Actions' payload are not simple JSON-y objects (for legacy migration reasons) but complex objects w/ methods and some state and all that noise.

@zalmoxisus
Copy link
Owner

If you don't see any exceptions in the console, then jsan should serialize them. The problem however is that it can take a lot of time to serialize them, probably that causes the issue.

@mAAdhaTTah
Copy link
Author

On the off-chance jsan chokes on an action, e.g. throws an error or something, would that show up visibly or possibly drop the action silently?

@zalmoxisus
Copy link
Owner

It would be thrown an exception in this case, seen in the console.

Do you have dispatched more than 4 actions in a second? If yes, then this part should be the problem. So, while serializing the history, a new action is dispatched and skipped. If that's the case, I will remove this part as being ineffective.

@zalmoxisus
Copy link
Owner

I removed that part in v2.6.0, which should fix the issue. If not, please reopen it.

@mAAdhaTTah
Copy link
Author

Ok cool, thanks. Is there a way to tell what version of the extension I have installed?

@zalmoxisus
Copy link
Owner

Sure, just look for the extension on chrome://extensions/. Chrome autoupdates the extensions, but it can take several hours.

@brianfegan
Copy link

brianfegan commented Oct 21, 2016

I'm running v2.8.2.2 and am also seeing this.

In my case, I have an action that has store.subscribe listeners firing other actions based on the results of the fired action (should conditions be met). And in those cases, it seems like only the final action gets picked up in the extension/console. However all the state updates are happening, and that final action displayed does show the correct state diff.

Also should point out that if I put a timeout around the action being dispatched in the store.subscribe listener everything shows in the extension. As opposed to it firing as soon as the state updates and the conditions in the listener are met.

@zalmoxisus
Copy link
Owner

zalmoxisus commented Oct 22, 2016

@brianfegan, could you please provide an example repo or jsfiddle to reproduce. You could fork our examples.

I'm trying to modify this action to

export function incrementAsync(delay = 1000) {
  return dispatch => {
+    dispatch(increment());
+    dispatch(decrement());
    setTimeout(() => {
      dispatch(increment());
    }, delay);
  };
}

and all 3 actions get picked as expected.

@brianfegan
Copy link

I'll work on putting together a jsFiddle, but here's some code that more clearly represents what I'm seeing. Its a bit different from what you put together.

There's a login fn that returns a fn (using thunk). That fn makes an async call that returns a promise. When that promise is fulfilled, I dispatch a LOGIN_SUCCESS action.

login(data) {
  return dispatch => user.login(data)
    .then(resp => dispatch({type:'LOGIN_SUCCESS', resp}));
}

Meanwhile, there's another file to manage a modal that contains the login form. To keep things isolated -- the login actions shouldn't care about the login modal UI -- I'm using store.subscribe in the management of the modal to know if a user has logged in so we can close the modal.

store.subscribe(() => {
  let state = store.getState().toJS();
  if (state.loginModal.isOpen && state.auth.authorized) {
    store.dispatch({type:'CLOSE_LOGIN_MODAL'});
  }
}); 

What happens is LOGIN_SUCCESS gets dispatched, which immediately dispatches CLOSE_LOGIN_MODAL as well (since those conditions are met). Redux picks them both up and all states are updated as expected. However, the dev tools extension only shows CLOSE_LOGIN_MODAL. Yet it shows the state changes that happened in both LOGIN_SUCCESS and CLOSE_LOGIN_MODAL merged together as if they happened in CLOSE_LOGIN_MODAL.

However, if I wrap a setTimeout around the action dispatched in the subscribe listener...

store.subscribe(() => {
  let state = store.getState().toJS();
  if (state.loginModal.isOpen && state.auth.authorized) {
    window.setTimeout(() => store.dispatch({type:'CLOSE_LOGIN_MODAL'}), 0);
  }
}); 

...then the dev tools extension displays both LOGIN_SUCCESS and CLOSE_LOGIN_MODAL.

@zalmoxisus
Copy link
Owner

zalmoxisus commented Oct 23, 2016

@brianfegan, thanks for the details, I can reproduce it. It's weird but seems to be as expected:

You may call dispatch() from a change listener, with the following caveats:
...
3. The listener should not expect to see all state changes, as the state might have been updated multiple times during a nested dispatch() before the listener is called. It is, however, guaranteed that all subscribers registered before the dispatch() started will be called with the latest state by the time it exits.

In other words the extension's subscribe gets the last change (even though it's invoked 2 times) in case when dispatch is from inside a store.subscribe.

I managed to solve this by moving extension's subscribe from setTimeout, which was added recently. However we need that for iframes. So, the problem will remain just when the app is from inside an iframe.

Another solution would be to count actions, so we'll pick the right one from the history even if the current one is not the last.

I'll think which one to choose, and will publish a patch tomorrow. Most likely, I'll go with the first one for now, as it's a regression from v2.8.2.

Another problem with using store.subscribe like in your case is that it will cause side effects while time travelling. So, when moving back and forth you'll have a lot of new CLOSE_LOGIN_MODAL actions in the history (as the subscribe is invoked and the condition is met). I'd suggest to use a middleware for this as I described here. So, you can lock those changes. In case you still want to dispatch from inside the subscribe and to use timetravelling there's an undocumented window.__REDUX_DEVTOOLS_EXTENSION_LOCKED__ to check before dispatching.

zalmoxisus added a commit that referenced this issue Oct 24, 2016
@brianfegan
Copy link

Thanks for the update, @zalmoxisus!

I'll also look into the suggestion you made. (But that CLOSE_LOGIN_MODAL will only fire if the redux store state has the modal as open and our used as authorized / logged in. So if I went backwards in state to a snapshot where the user isn't logged in, it wouldn't fire.)

Do you have any idea where the fix you committed^ will be pushed and available in the extension?

@zalmoxisus
Copy link
Owner

@brianfegan, should work now in 2.8.4. Let me know if there are still any troubles there.

@brianfegan
Copy link

Confirmed as fixed on my end. Thanks, @zalmoxisus!

@mAAdhaTTah
Copy link
Author

mAAdhaTTah commented Nov 29, 2016

This is definitely resolved for me with the latest version. I will also mentioned, in reviewing the code, there was a mutation in the reducer, so the same array was being returned, rather than a new one, which (maybe?) caused some issues as well, in case anyone else has this issue.

@sktguha
Copy link

sktguha commented Feb 10, 2021

Hello, not sure what is the right place to ask this , but for my case if a middleware for example "swallows" actions, i.e doesn't dispatch that action forward as either next or store.dispatch , it doesn't appear in the Redux devtools. I haven't set any kind of history limit, or done any kind of filtering etc.

Any command line param I can pass to customise that from here , /~https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md ?

@rahulbansal16
Copy link

I was facing the same issue. The reason was the limit in the redux dev tools was set to its default value of 50.

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